How can I prevent angular from updating the ngModel when the ngOptions array changes? Angular seems to set ngModel to null when the ngOptions array changed.
.controller('myController', function($scope) {
var vm = this;
vm.options = [];
vm.selected = null;
vm.getOptions = function(id) {
$http.get().done(function(response) {
vm.options = response.data;
});
};
}
say vm.selected = "1";
when vm.getOptions is called, the select options are being repopulated as expected, but angular seems to set vm.selected to null
How can I keep vm.selected = "1" after vm.options changes?
EDIT:
so I tried to set vm.selected after vm.options was set, however angular set vm.selected to null after my controller code runs.
so I tried to do:
$timeout(function(selected) {
vm.selected = selected;
}, 0, true, vm.selected);
this successfully sets vm.selected to the previous value, however the view isn't updated.
EDIT:
the html is:
<select name="myOption" ng-model="vm.selected"
ng-options="option.id as option.name for option in vm.options track by option.id">
<option value="">Select an option</option>
here is a plunkr to demonstrate. 1st, select an option, the click the update option button.
Be careful when using select as and track by in the same expression.
ngOptions
You're using the id as value for ngModel. you cannot track option.optionId on this. You should use the option instance instead:
<select ng-model="vm.selected"
ng-options="option as option.optionTitle for option in vm.options track by option.optionId">
<option value="">Select an option</option>
</select>
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope, $http) {
var vm = this;
vm.selected = null;
vm.options = [{optionId: 1, optionTitle: "one"}, {optionId: 2, optionTitle: "two"}];
vm.updateOptions = function() {
vm.options.push({optionId: 3, optionTitle: "three"});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<body ng-app="app" ng-controller="MainCtrl as vm">
<select ng-model="vm.selected" ng-options="option as option.optionTitle for option in vm.options track by option.optionId">
<option value="">Select an option</option>
</select>
<hr/>
vm.selected = {{ vm.selected }}
<br>
<button ng-click="vm.updateOptions()">Update Options</button>
<br>
</body>
Due to the numerous request for resetting the model on options change, Angular has made sure that the model value resets after the ng-options change for the versions > 1.4. However this will continue to work the same in the older versions of Angular.
Click here for the reference
In order to achieve the desired functionality, i would recommend you to use ng-repeat on options rather than ng-options on select.
<select ng-model="vm.selected">
<option value="">Select an option</option>
<option ng-repeat="option in vm.options track by option.optionId" value="{{option.optionId}}">{{option.optionTitle}}</option>
</select>
look at this plnkr example
hope this helps you!
This is one of such situation I got burnt myself due to not treating the model as object of the option and resorting to property of the selected option
How can I keep vm.selected = "1" after vm.options changes?
The vm.selected is a number not an object. It needs to be an object and must be the reference in the options
I made very small change to illustrate and get it to work.
First vm.selected treat it as object by following changes. Notice model is no longer optionId.
ng-options="option as option.optionTitle for option in vm.options track by option.optionId"
Second in the controller we are initializing the model as an object and a reference to the options.
vm.options = [{optionId: 1, optionTitle: "one"}, {optionId: 2, optionTitle: "two"}];
vm.selected = vm.options[1];
Also modified the plunkr for other changes related to optionId keeping unique. However those changes don't contribute to the point in question.
Related
nameList contains [“Julia”, “Evan”, “Tomas”];
select ng-model=“names” ng-options=“x for x in nameList”
In controller, I have a service api call GetNameByID/{id}”and depending on the id, I want to initialize the dropdown value of the modal form.
So if the user clicks ID 1, the dropdown defaults to Julia.
The problem is within the service call, when I try to initialize the model by doing $scope.names = data, it adds an empty option at the top instead of selecting Julia. When I console.log(data), it prints “Julia” but it becomes <option value=“?”></option>
How can i fix this?
So Lets have a HTML example for this case:
<div ng-app ng-controller="MyCtrl">
<select ng-model="names" ng-options="item for item in nameList">
</select>
<p>Selected : {{names}}</p>
<button ng-click="Update(2)"> Update(1)</button>
</div>
and Conrtoller has one service call which update your dropdown accordingly based on index.
function MyCtrl($scope) {
$scope.names = "Julia"
$scope.nameList = ["Julia", "Evan", "Tomas"];
$scope.Update = function(_value){
$scope.names = $scope.nameList[ parseInt(_value)] ;
}
}
Please have a look into running code, jsfiddle.
You can just use ng-init to initialize the dropdown first value like so:
<select ng-model="names" ng-init="names = data[0]" ng-options="x for x in data">
<option value="">Select</option>
</select>
Where [0] in data[0] is the position of the array.
Here is an example where you can set the option
In html file
<select ng-model="selectedName" ng-options="x for x in nameList"></select>
In js file
app.controller('myCtrl', function($scope) {
var id = 1;
$scope.names = ["Julia", "Evan", "Tomas"];
$scope.selectedName = $scope.names[id-1]; <---- here you can pass you id.
});
subtract id with 1 because array start with 0. Hope this is what you want to acheive.
I'm trying to get a select box working in Angular. The problem I'm experiencing is to do with ng-init and setting it's default value from an object which is created during runtime. Heres my code:
<select
ng-model="settings.editing.panel.data.production_company"
ng-change="settings.editing.panel.data.production_company = selectValue"
ng-init="selectValue = settings.editing.panel.data.production_company"
>
<option
ng-repeat="(key, value) in lists.production_companies"
value="{{key}}"
ng-selected="{{selectValue}}"
>
{{value}}
</option>
</select>
"lists.production_companies" is a simple key-value array of names, populated during initial page render, updated by ajax.
The object "settings.editing.panel.data" starts its life as NULL, but later is loaded with a correctly formatted object which contains the property "production_company".
I have found setting ng-init to something like "ng-init="selectValue = 3" works fine. Setting a $scope.test = 3, then setting "ng-init="selectValue = test" works fine too.
However, my dynamic value does not work. How can I use my dynamically created object to set the value of this select box during runtime with the set-up I have?
<select
ng-model="settings.editing.panel.data.production_company"
ng-options = "option as option.keyName for option in list.production_companies"
> <!--set keyName equal to your object's key-->
</select>
Then in your controller
$scope.settings.editing.panel.data.production_company = list.production_companies[0] // Or which value you want to assign
You question confused me somehow. The following snippet is a working one, is that what you want?
'use strict';
angular.module('DemoApp', []);
angular.module('DemoApp').controller('DemoCtrl', ['$scope', function($scope){
$scope.lists={
production_companies: { "0": "prod 1", "1":"prod_2" },
};
$scope.settings={
editing: {
panel: {
data: null
}
}
};
$scope.setData=function(data){
$scope.settings.editing.panel.data={
production_company: data
};
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="DemoApp" ng-controller="DemoCtrl">
<select ng-model = "settings.editing.panel.data.production_company">
<option ng-repeat = "(key, value) in lists.production_companies" value = "{{key}}">{{value}}</option>
</select>
<div>You select: {{settings.editing.panel.data.production_company}}</div>
<button ng-click="setData('0')">Set Data to Prod1</button>
<button ng-click="setData('1')">Set Data to Prod2</button>
</div>
In my circumstances I was able to change my backends data format to set an object like:
{"id": 1, "name":"prod comp 1"}
and then change my select model accordingly. In hindsight I needed this for the ID anyway.
<select
ng-model="settings.editing.panel.data.production_company"
>
<option
ng-repeat="option in settings.lists.production_companies"
value="{{option.id}}"
ng-selected="{{option.id}} == settings.editing.panel.data.production_company"
>
{{option.name}}
</option>
</select>
In Angular.JS, is there a way to bind two different ng-models when a select drop down option is selected?
Angular code:
<select ng-model="vm.data.styleId" ng-options="item.id as item.name for item in vm.getStylesData.styles">
<option value="">Select a Style</option>
</select>
Results in:
<option value="{{item.id}}">{{item.name}}</option>
With the Angular code I have so far, when an option is selected, it will save the option's value to the ng-model. In this case item.id is bound to vm.data.styleId.
However in addition to this, I also need to bind the 'item.name' of the selected option. Basically, when an option is selected, I need to bind both the item.id to vm.data.styleId, and the item.name to vm.data.name.
Is there an easy way to do this using Angular.JS?
Solution (using the answer from lisa p.):
In the View:
<select ng-model="vm.styleItem" ng-change="vm.getDetails()" ng-options="item as item.name for item in vm.getStylesData.styles">
<option value="">Select a Style</option>
</select>
Inside the controller:
vm.getDetails = function () {
// set the values of the select drop down
vm.data.styleId = vm.styleItem.id;
vm.data.style = vm.styleItem.name;
}
You can bind to an object containing both values like
item = { styleId: 23, name: "the name" }
vm.data = {{ styleId: ..., name: ... }}
then you bind to vm.data with
<option value="{{item}}">{{item.name}}</option>
Controller
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.vm.data.styleId = "";
$scope.item = {id : '1', name : 'name'};
});
html
<div ng-controller="myCtrl">
<select ng-model="vm.data.styleId" ng-options="item.id as item.name for item in vm.getStylesData.styles">
<option value="{{item}}">{{item.name}}</option>
</select>
</div>
Make an object which holds both id and name and pass that object as value to option
I am unable to update value of select from AngularJs.
Here is my code
<select ng-model="family.grade" >
<option ng-repeat="option in options" value='{{option.id}}'>{{option.text}}</option>
</select>
Here are the options which i am using to populate my select
var options = [{text:'Pre-K',id:'Pre-K'},
{text:'K',id:'K'},
{text:'1',id:'1'},
{text:'2',id:'2'},
{text:'3',id:'3'},
{text:'4',id:'4'},
{text:'5',id:'5'},
{text:'6',id:'6'},
{text:'7',id:'7'},
{text:'8',id:'8'},
{text:'+',id:'+'}];
Here is mu js code.
$scope.$watch("family_member.date_of_birth" ,function(newValue, oldValue){
$scope.family.grade = "1"
})
When ever value of family_member.date_of_birth changes it should set they value of select to 1. But this change is not visible on UI.
You should use ngSelected to select the option.
it could be something like this:
<select ng-model="family.grade" >
<option ng-repeat="option in options"
value='{{option.id}}' ng-selected="family.grade==option.id">
{{option.text}}</option>
</select>
Hope this helps.
I think you are looking for the track by clause of ng-options:
<option ng-repeat="option in options track by option.id">{{option.text}}</option>
However, you will still need to supply an object with an id property to set:
$scope.$watch("family_member.date_of_birth" ,function(newValue, oldValue){
$scope.family.grade = { id: "1" }
})
The options array indiviual elements are objects. So the respective ng-model also need to be an object. So even when it is being changed in js, the respective object has to be provided rather than a string.
Sample demo: http://plnkr.co/edit/naYcnID29SPa90co0leB?p=preview
HTML:
JS:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.options = [{text:'Pre-K',id:'Pre-K'},
{text:'K',id:'K'},
{text:'1',id:'1'},
{text:'2',id:'2'},
{text:'3',id:'3'},
{text:'4',id:'4'},
{text:'5',id:'5'},
{text:'6',id:'6'},
{text:'7',id:'7'},
{text:'8',id:'8'},
{text:'+',id:'+'}];
$scope.family = {};
$scope.family_member = {
date_of_birth: '10-Jan-1986'
};
$scope.$watch("family_member.date_of_birth", function(newValue, oldValue) {
$scope.family.grade = $scope.options[2];
});
});
I am generating some <option> elements using the ng-repeat directory. Using ng-repeat instead of ng-options is intentional.
However, it generates an empty option in addition to the actual array. Here's the code:
<select name="type" class="form-control" ng-model="selected_type" ng-change="select_change()" >
<option ng-repeat="type in types" value="{{type.value}}">{{type.name}}</option>
</select>
$scope.types = [
{value: '1', name: 'Sale'},
{value: '2', name: 'Other'}
];
$scope.selected_type = $scope.types[0].value;
And a fiddle: http://jsfiddle.net/HB7LU/521/
Here's a working fiddle, using ng-options
http://jsfiddle.net/HB7LU/527/
<select ng-model="selected_type" ng-change="select_change()" ng-options="c.name for c in types">
Then on script.js:
$scope.selected_type = $scope.types[0];
With that said, since you're just partly using angularjs you can just map the data in an array before you actually post in say in PHP.
try ng-options instead of making options tag yourself:
<div ng-controller="MyCtrl">
<select ng-model="selected_type" ng-change="select_change()" ng-options="type.value as type.name for type in types">
</select>
</div>
http://jsfiddle.net/aBPdv/
var myApp = angular.module('myApp', []);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.types = [
{value: '1', name: 'Sale'},
{value: '2', name: 'Other'}
];
$scope.selected_type = $scope.types[0].value;
$scope.select_change = function(x){
alert($scope.selected_type);
}
}
Just use the ng-model attributes on your option tag not on your select tag (use it where the ng-repeat is defined) like that :
<select ng-change="select_change()">
<option ng-model="selected_type" ng-repeat="type in types" value="{{type.value}}">{{type.name}}</option>
</select>
Then change your
$scope.selected_type = $scope.types[0].value;
to
$scope.selected_type = $scope.types;
But your ng-change will not work because no ng-model attribute is set so no ngModelController is assign to this element.
So if you want to know when the value of the select change you have to do a directive on the select element.
For all these reasons ng-options is always and i say always the right direction for a select input usage.