Ember Select populated by other Ember Select not updating selection binding - javascript

I'm new to Ember.js and I'm trying to figure out how Select views bind their selection to the controller. I have this template:
{{view Ember.Select
contentBinding="content"
selectionBinding="selectedCompany"
optionLabelPath="content.name"}}
{{view Ember.Select
contentBinding="selectedCompany.employees"
selectionBinding="selectedEmployee"
optionLabelPath="content.name"}}
Employee: {{selectedEmployee.name}}
Age: {{selectedEmployee.age}}
I find that the second select does update when selectedCompany changes, but I can't reference the values of name or age in selectedEmployee until I change the second select's value to a different value physically.
How do I make it so that the selectedEmployee is set when the first select changes, such that I can use it's value?
For better clarity, I have my working code here.

Changing content of second selectbox does not actualy change its selection. You have to do it manually, for example by adding following method to controller
onChangeCompany : function() {
if (!this.get('selectedCompany.employees').contains(this.get('selectedEmployee'))) {
this.set('selectedEmployee', this.get('selectedCompany.employees').objectAt(0));
}
}.observes('selectedCompany')
It stil needs some non-null and array-range checking, but does the job - if you select an employee and then change company, employee will change as well.

Related

selected boolean value on angular ng-options

The boolean value assigned to the model doesn't pre-select the corresponding option - shows first an empty option instead:
Select:
<select data-ng-model="scriptData.privacy" data-ng-options="privacyOption.value as privacyOption.label for privacyOption in privacyOptionsSelect track by privacyOption.value"></select>
Options in the controller:
$scope.privacyOptionsSelect=[
{
label:'Registered users only can view this',
value: false
},
{
label:'Anyone with the link can view this',
value: true
}
];
scriptData.privacy is set to false.
You should be careful when using the ngOptions expression with the format:
select as label for value in array
together with track by. This is because track by is applied to the value assigned to your ngModel, so if your selection is in the form privacyOption.value, the track by expression is actually applied to the value. This is the reason it doesn't successfully select the initial value.
To fix this you have two options. You can either just skip track by. This would work:
<select data-ng-model="scriptData.privacy"
data-ng-options="privacyOption.value as privacyOption.label for privacyOption
in privacyOptionsSelect"></select>
Or you could change the select as-expression to select the entire privacyOption-object. This would work as well (note the ngModel-directive changed as well):
<select data-ng-model="scriptData"
data-ng-options="privacyOption as privacyOption.label for privacyOption
in privacyOptionsSelect track by privacyOption.value"></select>
For a full (and probably better) explanation, I recommend the ngOptions documentation.
try ng-repeat instead of ng-options by applying the ng-repeat to option elements inside the select.

How to use ng-repeat inside a directive proper way in angularjs

Plunkr
I made a autofill dropdown using angular custom directive.All is working fine.
But I want to make this directive reusable!!!!
Currently my directive is tightly depended on Id and Name property of selected item.
I want to assign text property(Which I want to bind the text into list items html) and value property(which will be available in my app controller) like textfield="Name" and value-field="Id".
Imagine If my data object does not contain Name or Id property , my
directive would not work.
HTML:
<autofill-dropdown items="searchCurrencies"
textfield="Name" valuefield="Id" selected-data="Id" urllink="/api/SetupCurrency/Autofill?filter=">
</autofill-dropdown>
Template :
<div class="pos_Rel">
<input placeholder="Search Currency e.g. doller,pound,rupee"
type="text" ng-change="SearchTextChange()" ng-model="searchtext"
class="form-control width_full" />
<ul class="currencySearchList" ng-show="IsFocused && items.length">
<li class="autofill" ng-repeat="item in items" ng-click="autoFill(item)">
{{item.Name}}
</li>
</ul>
</div>
So,finally what I want to accomplish , I'm going to bind Name property(or other,depends on what value I set to "text-field" attribute onto my html) to listitems and whenever user select an item, it will give me the selected Id(or other property ,depends on what value I set to "value-field" attribute onto my html).
Plunkr Here
Update:
I think my question not so clear.
I have written same directive 2 times to accomplish and also 2 times same template :(
Please look through my updated plunkr.
Updated Plunkr
I want to say that I am not quit sure if I understood your question in the right way so I try to repeat it.
textfield="Name" valuefield="Id" selected-data="Id"
You want to store the Value of the Property of the selected Item of your custom directive.
The Value should be stored in the Variable provided in the attribute "textfield"
The attribute "valuefield" should define the name of the property of the selected Object
If this is the case you have to get rid of the two-way databinding for your valuefield. Because you only want to provide a String (like "Id" or "Name").
I altered your plunkr again. First of all I made the new scope variables:
scope: {
'items': '=',
'urllink':'#',
'valuefield':'#',
'textfield':'=',
'Id':'=selectedData'
}
Valuefield is now only a text binding. So if you want to change it in the angular way you have to provide a scope variable outside of the directive and a '=' twoway binding inside :D
$scope.autoFill = function (item) {
$scope.IsFocused = false;
$scope.searchtext = item.Name;
$scope.Id = item.Id;
$scope.textfield = item[$scope.valuefield];
}
Also I added the last expression to your autofill function. The name of the property (valuefield) will be written into the textfield variable which is linked with your outside scope (in this case "Name"):
textfield="Name"
If this is not what you asked I am sorry but I am new to stackoverflow and I still can not comment :P
https://plnkr.co/edit/zE1Co4nmIF3ef6d6RSaW?p=preview

How can I keep ng-model in sync with a select element after ng-options removes the selected option

I have a select element with an ng-model and ng-options on it. ng-options makes the possible selections dynamic however I have noticed that when ng-options updates the options ng-model is not also getting updated. For example if the select element has the value of "foo" selected then the ng-options model is updated and "foo" is no longer an option the selector updates to blank but ng-model still shows "foo" as its value. I would expect that ng-model would update as well to equal null. The only thing I can think of is to add a watch on items but that seems kind of lame. What is the best way to get ng-model to stay in sync with the select element in this scenario?
<div ng-controller="MyCtrl">
<p>Selected Item: {{foo}}</p>
<p>
<label>option</label>
<select ng-model="foo" ng-options="item.val as item.label for item in items">
<option value="">Select Something</option>
</select>
</p>
<button ng-click="remove()">Remove Second Item Option</button>
<p>{{items}}</p>
</div>
Here is the jsfiddle to illustrate the issue. http://jsfiddle.net/dberringer/m2rm8Lh6/2/
Note: I'm aware I could manually update the foo value with the delete method. This method is just to illustrate the issue.
Thanks for your feedback.
Update: I fixed a typo where referred to ng-options as ng-select.
change the button like
<button ng-click="remove(2)">Remove Second Item Option</button>
change the remove function
$scope.remove = function(removeIndex) {
if($scope.foo == removeIndex) {
$scope.foo = null;
}
$scope.items.splice(removeIndex-1,1);
};
here is the Demo Fiddle
Reason is,
ng-change is not going to trigger when,
if the model is changed programmatically and not by a change to the input value, check the Doc here
so u are not changing the select value by changing the select box instead do it using a button (programmatically) so angular will not trigger the change event on the select element and then angular doesn't know model is changed ,this might be the reason.
then what u need to do is change model value manually as $scope.foo = null;
I think angular didn't check that, once the ngOptions value changes, angular didn't do a check to see if the ngModel is exists in ngOptions.
angular.js
line 21371:
self.databound = $attrs.ngModel;
line 21828 - 21840:
return function (scope, element, attr) {
var selectCtrlName = '$selectController',
parent = element.parent(),
selectCtrl = parent.data(selectCtrlName) ||
parent.parent().data(selectCtrlName); // in case we are in optgroup
if (selectCtrl && selectCtrl.databound) {
// For some reason Opera defaults to true and if not overridden this messes up the repeater.
// We don't want the view to drive the initialization of the model anyway.
element.prop('selected', false);
} else {
selectCtrl = nullSelectCtrl;
}
You can see above code checks which option should be selected when generated the options, but i can't find a reverse check when ngOptions got updated.

Ember TextField valueBinding to controller issue

I am using the Twitter typeahead.js plugin. So to use it I am extend Ember's TextField. The plugin all works fine. Now I just want to make the value accessible inside the controller.
When I use the value binding inside the view class, it works fine. Here is the bin example. Here the value gets set initially and updates later. To test the text view type 'aaa'.
App.TypeAhead = Ember.TextField.extend({
classNames: ['cmp-typeahead'],
attributeBindings: ['id','value'],
valueBinding: 'targetObject.airportCode',
....
});
But when I try to set the value binding via the template, it doesn't seem to work. Here is the bin example. To test the text view type 'aaa'.
{{view App.TypeAhead data=airports valueBinding="view.targetObject.airportCode"
id="fromAirportCode"}}
What am I doing wrong?
Since the view helper will keep the current controller, it's as simple as:
{{view App.TypeAhead data=airports valueBinding="airportCode"
id="fromAirportCode"}}
Example: http://emberjs.jsbin.com/ciwiv/1/edit

Multiple selects instead of multi select in Ember application

in Ember multiselects can be created using the multiple property of the Ember.Select view (e.g. in this post).
What I want to do is substituting a multiselect with multiple "normal" selects, which are all bound to the same array. Let's say I have two single selects, then both should be bound to an array fooArray. When I select foo in the first select and bar in the second one, then fooArray should be ['foo', 'bar'].
Any ideas on how to do that?
Kind regards,
Marius
You can set a selectionBinding for each select and a computed property taha makes the array... sure there are better ways to do this... it depends of the number of selects you deal with, because, in this example, the returned array is recalculated each time you get it
and this don't scale very well
App.SelectionController = Ember.ObjectController.extend({
select1Value:null,
select2Value:null,
select3Value:null,
selectedArray:function{
return Ember.Array(this.get('select1Value'),this.get('select2Value'),this.get('select2Value'));
}.property('select1Value','select2Value','select3Value')
});
In the view
{{view Ember.Select
contentBinding="YourSelectContent"
selectionBinding="App.SelectionController.select1Value"
[...]
{{view Ember.Select
contentBinding="YourSelectContent"
selectionBinding="App.SelectionController.select2Value"
[...]
{{view Ember.Select
contentBinding="YourSelectContent"
selectionBinding="App.SelectionController.select3Value"
[...]

Categories

Resources