focus-out event in Ember.Select view - ember.js

I have used Ember.Select view as follows.
{{view "select" content=people
optionLabelPath="content.fullName"
optionValuePath="content.id"
prompt="Pick a person:"
selection=selectedPerson}}
Now I want to add focus-out="showErrors" event listener to this select view in order to handle some validation. This works perfectly with Ember.TextField and Ember.TextArea. But I noticed the focus-out does not work with Ember.Select view.
It would be really nice if someone can provide a solution to this problem

Could you add an observer to selectedPerson so that when the user changes the dropdown value this will trigger your validation.
Older syntax:
validatePersonChange: function(){
//do validation here
}.observes('selectedPerson')
Newer syntax:
const { observer } = Ember;
...
validatePersonChange: observer('selectedPerson', function(){
//do validation
})

Related

Ember Select not firing on Change

I know this is a common problem, but I can't get an Ember.Select view to fire on its value changing. I'd either like to update the selectedInvitation based on the selection in the drop down, or call an action that will perform this behavior.
I've tried variations on Binding Action in Ember.Select and haven't had any luck.
models/uservisit.js
Models.Invitation = DS.Model.extend({
sameSeriesOpenInvitations: DS.hasMany('uservisit', {
async: true
})
});
controllers/user/invitations_controller.coffee
Visitdays.InvitationsController = Ember.ArrayController.extend
selectedInvitationObserver: (->
debugger
if #get('selectedInvitation')
#get('selectedInvitation')._data.event
).observes('selectedInvitation')
actions:
setSelectedInvitation: (invitation) ->
debugger
if invitation
#set 'selectedInvitation', invitation
invitations.emblem
.input-group.full-width
= view Em.Select contentBinding=selectedInvitation.sameSeriesOpenInvitations optionValuePath="content" optionLabelPath="content.event.startTimeFormatted" value="selectedInvitation" class="form-control"
Thanks to #ahmed.hoban who got me in the right direction. I didn't need an action or anything. Since I wanted to deal with the object and not just the id, I really only needed to change the Ember.Select view's selection attribute to the object I wanted to observe change:
.input-group.full-width
= view Em.Select content=selectedInvitation.sameSeriesInvitations optionValuePath="content.id" optionLabelPath="content.visit.startTimeFormatted" selection=selectedInvitation class="form-control"

How to get the selected model for a given row onChange with Ember.Select

I have a custom Ember.Select that I'm overriding the "change" event to handle the event myself (to fire off an xhr for example)
In my handlebars file, I add a select to each row (ArrayController backed)
{{#each thing in controller}}
{{view App.CustomSelect value=thing.category content=configuration optionValuePath="content.id" optionLabelPath="content.name"}}
{{/each}}
In my javascript I handle the event like so
App.CustomSelect = Ember.Select.extend({
change: function(x) {
//in here I can only get the selected option / value
//what I really need is both that value (above)
//and the model for this given row
}
});
How can I get the model bound to that specific select in the change event?
Looking through my own code, to get the model you need to do the following:
App.CustomSelect = Ember.Select.extend({
change: function(x) {
var selectedModel = this.get('selection');
}
});

Ember, how to copy value/label of selected item of Ember.Select to next TextField?

I have a simple construction Ember.Select holding some predefined strings and Ember.TextField next to it:
{{view Ember.Select
prompt="Choose..."
contentBinding="predefinedLabels"
optionValuePath="content.value"
optionLabelPath="content.label"
}}
{{view Ember.TextField valueBinding='view.newLabel' action='saveNewLabel'}}
I need to on select change get it's current value (if not prompt) and set it to the TextField and then reset the select to the prompt state - sounds trivial, but I have no idea how to do that :( I tried by using selectionBinding but problem is that these sets Select+ TextField are created dynamically. with common jQuery I would do it with common change listener added to the all select tags with some specified class, what is equivalent of the similar behavior in the Ember? (or what is proper way to do what I need?
You can still do just that with jQuery. Just put the relevant code (attaching change listeners) into the didInsertElement method of your current view.
See this working jsFiddle.
App.ApplicationView = Ember.View.extend({
didInsertElement: function() {
var self = this;
this.$('select').change(function() {
self.$('input').val(self.$('option:selected').text());
self.$("option:selected").removeAttr("selected");
});
}
});
Do I understand you correctly?
Is this the behaviour you are looking for: http://jsbin.com/aqaYEgo/3/edit
Basically:
App.ApplicationController = Ember.ObjectController.extend({
selectedLabel: null,
actions: {
saveNewLabel: function() {
console.log('Saving label: ' + this.get('selectedLabel.value'));
}
}
});
{{view Ember.Select
prompt="Choose..."
contentBinding="model"
optionValuePath="content.value"
optionLabelPath="content.label"
selectionBinding="selectedLabel"
}}
{{view Ember.TextField valueBinding="controller.selectedLabel.value" action='saveNewLabel'}}
Hope it helps.

focus() on Select field fired before Ember updates disabledBinding attribute

In my application I have an extended Em.Select view:
App.SelectField = Em.Select.extend({
attributeBindings: ['disabled'],
actions: {
setFocus: function(){
this.$().focus();
}
}
});
Which is used in my handlebar template:
{{view App.SelectField
viewName="cbAddressType"
disabledBinding='getIsDisabled'
contentBinding="controllers.addressTypes"
optionValuePath="content.id"
optionLabelPath="content.addressTypeName"
valueBinding="getSetAddressType"}}
The view has a disabledBinding bound to the view's controller property getIsDisabled. When this property changes, the Select view is either enabled or disabled. This works just fine.
However, I also have an action on the template:
<button {{action "editRecord" view.cbAddressType}}>Edit</button>
This calls the controller's editRecord action:
actions: {
editRecord: function (fieldToFocusOn) {
this.toggleProperty('isEditing');
if (fieldToFocusOn && this.get('isEditing'))
{
fieldToFocusOn.send("setFocus");
}
}
}
Which sends the setFocus action to the above SelectField, which in turn runs the focus() method on the select control.
The problem is that focus() is fired BEFORE the disabledBinding attribute on the Select is updated with the bound property's changed value in the controller. The control cannot receive the focus until it is enabled. I tried a while select.disabled [wait] loop but that just led to an infinite loop as it appears that the view is not refreshed until after the setFocus is called - they are not run asynchronously.
What I also note is that on a Ember.TextField with a readonlyBinding instead of a disabledBinding that this methodology works fine: the text field's readonly attribute is removed before the focus() event is fired.
Grateful for any advice.
Not tested but could work. In your App.SelectField use:
setFocus: function(){
Ember.run.schedule('afterRender', this, function() {
this.$().focus();
});
}

Populating contents of Ember.Select view from RecordArray retrieved using Ember-data

I have a select list that is created using this code:
{{view Ember.Select
contentBinding="App.riskCategories"
optionValuePath="content.id"
optionLabelPath="content.name"
selectionBinding="riskCategory"
class="input-medium"}}
riskCategory is a property of the App.Facility model loaded for the template and the list of App.RiskCategory is populated with this code:
App.ready = function() {
App.riskCategories = App.RiskCategory.all()
}
This works fine and populates the select list but only with the sub-set of Risk Categories already loaded into the browser. If I call App.RiskCategory.find() from the browser console then the rest are loaded and the select list updates however I can't get the code working to do this for me.
So I tried:
App.ready = function() {
App.riskCategories = App.RiskCategory.find()
}
or:
App.ready = function() {
App.RiskCategory.find()
App.riskCategories = App.RiskCategory.all()
}
But both of these result in the following error:
Uncaught Error: Attempted to handle event `loadedData` on <App.Facility:ember417:1> while in state rootState.loaded.updated.uncommitted. Called with undefined
I'd appreciate any help or suggestions on a better way to populate the select list. These App.RiskCategory objects should be considered an immutable collection of constants stored in the db. Each of the App.Facility objects is associated with one of these App.RiskCategories
Thanks!
Try instead to set the categories in your route and access it in your template through the controller
APP.YourRoute = Ember.Route.extend({
setupController:function(controller,model) {
this._super(controller,model);
controller.set('riskCategories',App.RiskCategory.find());
},
});
Assuming your select view is within the same context as the controller, You get access to categories in your template this way:
{{view Ember.Select
contentBinding="controller.riskCategories"
optionValuePath="content.id"
optionLabelPath="content.name"
selectionBinding="riskCategory"
class="input-medium"}}
I solved this problem by wrapping the rendering of each App.Facility in a {{#if isLoaded}}
So the code looked somthing like:
{{#each client.facilities}}
{{#if isLoaded}}
{{view Ember.Select
contentBinding="App.riskCategories"
optionValuePath="content.id"
optionLabelPath="content.name"
selectionBinding="riskCategory"
class="input-medium"}}
{{/if}}
{{/each}}
It appears that the App.Facility object that setting the App.RiskCategory hadn't finished loading yet, so the default App.RiskCategory was being set and then when the dataLoaded event was fired, the exception was being thrown because the object had already been modified.
I had a similar problem and the solution using #isLoaded did not work for me. However, what did was to add a prompt property to the Ember.Selectelement. I suspect that that has to do with the asynchronicity of rendering the view and loading the data (in my case from FIXTURES, but as as far as I know DS.FixtureAdapter simulates time-lags in loading data).