问题
I've done a sample Ember.js integration with Chosen (https://github.com/harvesthq/chosen)
Coffeescript:
App.ChosenSelectView = Em.Select.extend({
didInsertElement: ->
@_super()
@$().chosen()
# Assumes optionLabelPath is something like "content.name"
@addObserver(@get("optionLabelPath").replace(/^content/, "content.@each"), -> @contentDidChange())
contentDidChange: ->
# 2 ticks until DOM update
Em.run.next(this, (-> Em.run.next(this, (-> @$().trigger("liszt:updated")))))
})
The thing that bothers me is I don't have a good idea about how much time do I need before triggering update on the Chosen widget. From my experiments 2 run loops is ok, but maybe there is a better way for the whole thing?
Full example at jsfiddle: http://jsfiddle.net/oruen/qfYPy/
回答1:
I think the problem is that your observer is notified kind of too early, meaning that the changes have not yet been written to the DOM.
I've hacked a little around and in the end I came up with a solution, which calls Ember.run.sync()
before the event for the chosen
plugin is triggered, see http://jsfiddle.net/pangratz666/dbHJb/
Handlebars:
<script type="text/x-handlebars" data-template-name="selectTmpl" >
{{#each items tagName="select" }}
<option {{bindAttr value="id"}} >{{name}}</option>
{{/each}}
</script>
JavaScript:
App = Ember.Application.create({});
App.items = Ember.ArrayProxy.create({
content: [Ember.Object.create({
id: 1,
name: 'First item'
}), Ember.Object.create({
id: 2,
name: 'Second Item'
})]
});
Ember.View.create({
templateName: 'selectTmpl',
itemsBinding: 'App.items',
didInsertElement: function() {
this.$('select').chosen();
},
itemsChanged: function() {
// flush the RunLoop so changes are written to DOM?
Ember.run.sync();
// trigger the 'liszt:updated'
Ember.run.next(this, function() {
this.$('select').trigger('liszt:updated');
});
}.observes('items.@each.name')
}).append();
Ember.run.later(function() {
// always use Ember.js methods to acces properties, so it should be
// `App.items.objectAt(0)` instead of `App.items.content[0]`
App.items.objectAt(0).set('name', '1st Item');
}, 1000);
回答2:
Michael Grosser posted his working ChosenSelectView here: http://grosser.it/2012/05/05/a-chosen-js-select-filled-via-ember-js
回答3:
This might work for you on Ember 1.0 and Chosen v0.12:
JavaScript:
App.ChosenSelect = Ember.Select.extend({
chosenOptions: {width:'100%', placeholder_text_multiple: 'Select Editors', search_contains: true},
multiple:true,
attributeBindings:['multiple'],
didInsertElement: function(){
var view = this;
this._super();
view.$().chosen(view.get('chosenOptions'));
// observes for new changes on options to trigger an update on Chosen
return this.addObserver(this.get("optionLabelPath").replace(/^content/, "content.@each"), function() {
return this.rerenderChosen();
});
},
_closeChosen: function(){
// trigger escape to close chosen
this.$().next('.chzn-container-active').find('input').trigger({type:'keyup', which:27});
},
rerenderChosen: function() {
this.$().trigger('chosen:updated');
}
});
Handlebars:
{{view App.ChosenSelect
contentBinding="options"
valueBinding="selectedOption"
optionLabelPath="content.name"
}}
来源:https://stackoverflow.com/questions/9968222/ember-js-chosen-integration