Ember.js: Wrapping JQuery component (Minicolors) - ember.js

I try to integrate the Minicolor JQuery component in Ember.js application.
Integration should be easy but it does not work for me... (input is displayed but without JQuery component)...
Minicolor integration guide:
https://github.com/claviska/jquery-miniColors
From doc: simply insert the js file and add the following input:
My js file:
App.ColorPicker = Em.TextField.extend({
type: 'minicolors',
attributeBindings: ['name'],
willInsertElement: function() {
;
}
});
The html file
{{view App.ColorPicker placeholder="Background color" name="color" valueBinding="App.MyController.backgroundColor"}}

I believe your issue is that ember is dynamically adding the <input type='minicolors' ... /> element after the initialization code for minicolors has already executed, causing your new minicolors input to not be initialized.
I got your example working by using the didInsertElement event instead of willInsertElement event to force minicolors to create the dynamically added App.ColorPicker element. The willInsertElement fires when the element is going to be inserted, but hasn't yet, and the didInsertElement will fire after the element has been inserted. I used the latest files from the minicolors github repository.
App.ColorPicker = Em.TextField.extend({
type: 'minicolors',
attributeBindings: ['name'],
didInsertElement: function() {
$.minicolors.init();
}
});
The only other issue I had was needing to make sure the css file and the png with the color picker graphical elements could be loaded. Apparently if the css and png files are not loadable the js portion doesn't work.

Related

EmberJS: multiple outlets within #each loop

I want to accomplish the following feature:
A list of entries - when a single entry is clicked, the details of this entry should be displayed below the current entry.
It should be possible to access a single entry via a route, e.g. tasks/1
My approach:
I tried to solve this by including {{outlet}} within my #each loop but that did not quite work.
All tutorials an solutions I found are based on a List -> Details approach where only a single outlet is used.
I have no idea how I could solve this problem. Is there a better solution?
This is not possible through routing. You are better off using a component that expands, loads and displays the details upon clicking.
//list.hbs
{{#each task in tasks}}
{{#task-loader task=task}}
{{#task-loader-trigger}}
//list ui
{{/task-loader-trigger}}
{{#task-loader-content}}
//details ui
{{/task-loader-content}}
{{/task-loader}}
{{/each}}
//task-loader.js
export default Em.Component.extend({
isOpen: false
});
//task-loader-trigger.js
export default Em.Component.extend({
click: function() {
//toggle isOpen
}
}};
//task-loader-content.js
export default Em.Component.extend({
classNameBindings: ['parentView.isOpen:show:hide'],
didInsertElement: function() {
//send request and load data
}
});
If you do want to maintain state (the currently open task), use query params. Hope this helps :)

Emberjs outlet inside a bootstrap popover

I'm using bootstrap popover in my app and I need to render an outlet inside it.
I have this nested route :
this.resource('pages', function(){
this.resource('page', { path: ':id' }, function(){
this.resource('edit', function(){
this.resource('images', function(){
this.resource('image', { path: ':image_id'}, function(){
this.route('edit');
})
});
});
});
});
When the user is here => /pages/1/edit/ when he click on an image it route to /images but render the {{outlet}} inside the popover like this :
<div class="popover-content hide">
{{outlet}}
</div>
This is my popover initialisation :
$img.popover({
html: true,
content: function() {
return $('.popover-content').html(); //need to have the outlet here
}
});
So far, it render correctly my outlet, but inside the images template, I have some button that modify the DOM and it doesn't update the html. Unless if I close and open the popover again I can see the modification.
Is it possible to render the outlet directly inside the code ? or is it possible to have my popover being updated ?
Thanks for the help.
See these links for an alternative approach to putting Ember stuff in Bootstrap popovers:
Bootstrap Popovers with ember.js template
https://cowbell-labs.com/2013-10-20-using-twitter-bootstrap-js-widgets-with-ember.html
Ember and Handlebars don't like this because it's basically copying the html content of a div and plopping it into another. But that html alone isn't everything that's needed. Ember is magic and there's lots of stuff happening in the background.
Your hidden div is real ember stuff, so let's try not to mess with it by calling .html() on it. My idea is to literally move the DOM itself instead.
first, modify your popover function call to always create this placeholder div:
content: '<div id="placeholder"></div>',
next, detach the content div from the dom in the didInsertElement of the view:
// get the popover content div and remove it from the dom, to be added back later
var content = Ember.$('.popover-content').detach();
// find the element that opens your popover...
var btn = Ember.$('#btn-popup-trigger').get(0);
// ... and whenever the popover is opened by this element being clicked, find the placeholder div and insert the content element
// (this could be improved. we really just want to know when the popover is opened, not when the button is clicked.)
btn.addEventListener("click", function() {
content.appendTo("#placeholder");
});
since the content div is immediately detached when didInsertElement is called, you can remove the "hide" css class from the content div.
edit: i tried this on my own project and it broke two-way binding. the controller updated my handlebars elements, but any two-way bound {{input}} helpers did not update the controller/model. i ended up using a single-item dropdown menu, and used this to prevent the menu from closing too quickly:
Twitter Bootstrap - Avoid dropdown menu close on click inside

Start foundation js in Ember (using ember-cli)

In my project I am trying to use Foundation's accordion but to no avail. Specifically I have followed this guide here https://coderwall.com/p/azjwaq but it doesn't work. It only works if I explicitly refresh the page, but If I navigate to another controller it stops working. Is this the correct way to initialize foundation 5?
I use foundation 5.3.3 with ember 1.8.0-beta1 and ember-cli 0.44.
Edit:
heads up! I managed to make it work. BUT the whole app now is really really really slow. Specifically I have this inititializer in app/initializer/foundation.js.
import Ember from 'ember';
export default {
name: 'foundation-config',
initialize: function() {
Ember.View.reopen({
startFoundation: function() {
Ember.run.scheduleOnce('afterRender', this, function(){
$(document).foundation();
});
}.on('didInsertElement')
});
}
};
Am I doing something wrong?
Maybe try this:
Stop initializing Foundation for each view. Try extending views which contain accordion to a separate object and then extend it.
App.FoundationView = Ember.View.extend({
didInsertElement: function () {
$(document).foundation();
}
});
App.ViewWhichNeedFoundation = App.FoundationView.extend({
...
})
Simply initializing foundation the normal way manually worked for me. Just before the closing body tag:
<script>
$(document).foundation();
</script>

Not rendering/removing sidebar based on route

Something I've been experimenting around with Ember for a couple of hours and can't work out. Hopefully it's just a terminology issue that I'm getting stumped on as I read through the Ember docs.
I have an application, that, for the most part, consists of a sidebar/top bar (called wrapper), and a footer.
My basic application.hbs looks like this (I'm using Ember App Kit to provide structure):
{{partial "wrapper"}}
{{outlet}}
{{partial "footer"}}
If this was the state of my application, it would work pretty well. Page content loads in the {{outlet}} fine.
My main issue is how to break out of this template structure in an "Ember" way (and preferably without going all jQuery and removing DOM elements willy-nilly).
I have a few routes that I don't want the wrapper and the footer to show on (they're full page login/forgot password routes, and a couple of minimal interface/no distractions modes).
I experimented with trying to remove the sidebar and footer by making the default template (application.hbs):
{{#if showWrappers}}
{{partial "wrapper"}}
{{/if}}
{{outlet}}
{{#if showWrappers}}
{{partial "footer"}}
{{/if}}
Where showWrappers is in the ApplicationController:
export default Ember.Controller.extend({
showWrappers: function() {
var routes = ['login'],
currentPath = this.get('currentPath'),
show = true;
routes.forEach(function(item) {
var path = new RegExp('^' + item + '*');
if (!Ember.isEmpty(currentPath.match(path))) {
show = false;
}
});
return show;
}.property('currentPath'),
});
Attemping to transition to /login from / using {{link-to}} returns in an error: Uncaught Error: Cannot perform operations on a Metamorph that is not in the DOM presumably because I'm removing things Ember wanted to keep (I am using {{link-to}} and {{bind-attr}} in the sidebar, so there are bindings there).
Aware that I could use actions and jQuery to hide elements of the page and bring them back for the "distraction free" mode, but I'd prefer to learn how to structure templates and use Routes with the renderTemplate hook potentially using this.render (?) to blow away the current DOM and rebuild from a different base (rather than application.hbs).
Thoughts? More than happy to clarify.
I have discovered disconnectOutlet, and have converted my partials into outlets:
{{outlet wrapper}}
{{outlet}}
{{outlet footer}}
Made my ApplicationRoute render to them by default:
export default Ember.Route.extend({
renderTemplate: function() {
this.render();
this.render('wrapper', {
outlet: 'wrapper',
into: 'application'
});
this.render('footer', {
outlet: 'footer',
into: 'application'
});
}
});
and then on the LoginRoute, I just run this.disconnectOutlet for both wrapper and footer, and seems to work pretty well.

Add Views to ContainerView with template containing "linkTo" and a custom controller won't work

I have the use case where I need to add custom views to a container view using a specific template and controller. Unfortunately this only works if I don't have the "linkTo" helper in my template. As soon as I add this I can't set a custom controller anymore.
<script type="text/x-handlebars" data-template-name="page1link">
<!-- remove this line and it will work -->{{#linkTo "page1"}}Go to Page 1{{/linkTo}}
<p>Link template</p>
</script>
App.IndexView = Ember.ContainerView.extend({
didInsertElement: function(){
var LinkView = Ember.View.extend({
templateName: "page1link",
controller: Ember.Controller.create()
});
for(var i = 0; i < 4; i++){
this.pushObject(LinkView.create());
}
}
});
I always get following exception:
Uncaught TypeError: Cannot call method 'lookup' of null
at following part of the ember code: Ember.LinkView
...
router: Ember.computed(function() {
return this.get('controller').container.lookup('router:main');
Uncaught TypeError: Cannot call method 'lookup' of null
}),
...
Somehow the container is not set in this case.
I've created a fiddle showing this issue. Is there a better way to implement this with ember?
JSFiddle Example
Thanks for any hints!
Have a look at the ember guides, specifically over here. They have a controller that displays a list of items each item wrapped in its own controller. While it seems you're trying to do this page by page (Not sure why), the principle is, I think, the same.
Let me know if I've missed the mark and I'll give it some more thought.
have a look at this stack overflow post for infinte scroll in a list using ember.