In AngularJS 1.3 app I have a form on which I get model and possible values for select controls asynchronously from backend. When I get model value before values used in ng-options, no options becomes selected in select control.
I managed to reproduce this behaviour:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $timeout) {
$scope.model = { value: 101 };
$timeout(function() {
$scope.model.values = [100, 101, 102, 103];
}, 1000);
});
view:
Options: <select ng-model="model.value"
ng-options="v for v in model.values">
<option value="">Select some...</option>
</select>
After timeout model has its old value 101 but no option is selected.
Currently I find a workaround by using ng-if="model.values" on select, but I feel that there should be better way to do it.
Could somebody explain why option is not selected?
Plunkr: http://plnkr.co/edit/4opZRJzdDfJhSNJx8RMF
EDIT: I opened Plunkr in Firefox and I started to work, then I back to Chrome and it didn't work looks like crossbrowser issue...
It looks like this is a regression in AngularJs 1.3.x.
The example you provided works fine in AngularJs 1.2.x and 1.4.x.
I agree with #PrimosK about issue.
The solution is to add tracking:
ng-options="v for v in model.values track by v"
example in Plunker
Related
I have a select element, and I want it populated with the result of a call to a resource via ngResource.
<select chosen=""
required
data-ng-model="coolStuffSelected"
data-ng-options="stuff for stuff in coolStuff"
class="chosen-select input-md"></select>
In my Controller I have
CoolStuffResource.query(function(result){
$scope.coolStuff = result;
console.log(JSON.stringify($scope.coolStuff));
// prints ["foo","bar","gaz","waka"]
});
I see the result logged, but the select is empty. What am I doing wrong?
Update: I tried this albeit hacky workaround, which is to access the ng-model :
MyCoolService.query(function(result){
$scope.coolStuff = result;
$scope.coolStuffSelected = null;
});
This works in Chrome, but does not work in Safari. Simply hardcoding the values works fine in both browsers:
$scope.coolStuff = ["foo", "bar", "gaz", "waka"];
Here's a working JsFiddle from your other question, demonstrating the returned data from there.
<select ng-model="selected" ng-options="d for d in data"></select>
JS:
function MyCtrl($scope) {
MyCoolResource.query(function(result){
$scope.data = result;
});
}
What does the JSON look like in your response? Your ng-options expression is most likely wrong. You need to tell it what you want displayed in your select.
Change your ng-options: so it looks something like this:
ng-options="stuff as stuff.label for coolstuff"
Change stuff.label to whatever property you want displayed in your select.
Take a look at this documentation: https://docs.angularjs.org/api/ng/directive/ngOptions
I wanted to set a default value to my ng-options by using ng-init, ng-model, etc. They didn't work at all. My code is following:
Angular
var app = angular.module('role', []);
app.controller('fooController', function($scope){
$scope.roles = [{id:1, name:"Administrator"}, {id:2, name: "Student"}];
$scope.user.roles = $scope.roles[0];
});
HTML
<body data-ng-app="role" data-ng-controller="fooController">
<select multiple class="form-control" data-ng-model="user.roles" data-ng-options="role.name for role in roles" required=""></select>
</body>
Here is my Plunkr.
Any help would be appreciated.
Update:
If you want to get directly to the reference used in this answer, here it is:
Reference:
Initial Selection In AngularJS ng-options with track by
Here's what worked for me:
app.controller('fooController', function($scope){
$scope.roles = [{id:1, name:"Administrator"}, {id:2, name: "Student"}];
$scope.user = {};
$scope.user.roles = [ $scope.roles[0] ];
});
There was an error in the plunk that user wasn't initialized, apart from this, Angular would compare every object in the ng-options array to every element in the ng-model array. JavaScript comparison not Angular comparison, comparing 2 objects even with same properties in JavaScript returns false (different objects).
Plunk: http://plnkr.co/edit/ccsAVvPACnN6Qzje7HcB?p=preview
.
Now, this is not ideal. Typically you want to correlate these based on ID or so, here's another way:
In HTML, use track by to tell AngularJS to compare IDs instead of entire objects:
<select multiple class="form-control"
data-ng-model="user.roles"
data-ng-options="role.name for role in roles track by role.id"
required=""></select>
Then in your controller, you can use any object without actually being in the array:
app.controller('fooController', function($scope){
$scope.roles = [{id:1, name:"Administrator"}, {id:2, name: "Student"}];
$scope.user = {};
$scope.user.roles = [ {id:1, name:"Administrator"} ];
});
Plunk: http://plnkr.co/edit/NKLXrwqwk36YfhBSXILN?p=preview
Note that I didn't even need the name property. It's just for making a proper object later, but it really isn't needed for matching now, try without it!
.
I wrote a detailed tutorial with an accompanying video on this initial selection problem and its variations. It's focused on single-select but multi-select is just using an array of objects instead of one object directly.
Check it out for more understanding -- highly recommended:
Initial Selection In AngularJS ng-options with track by
.
Let me know in comments if you are still struggling with this.
if your model is like $scope.user.roles = [1]; then your ng-options should be like this,
data-ng-options="role.id as role.name for role in roles"
this will select only the ID
if you do like data-ng-options="role.name for role in roles" then your model should be like
$scope.user.roles = [{id:1, name:"Administrator"}];
because this will select the whole object
and in your controller
$scope.user = {}; //this line should be add
because your trying to access a roles property of user but there is no user object defined, this will also occur a error
here is the Updated Plunker
here is the updated plunker1 plunker2 for your case of ng-options
you can use ng-init here. please check.
like this
<body ng-init="role.name = roles[0].name" data-ng-app="role" data-ng-controller="fooController">
<select multiple class="form-control" data-ng-model="user.roles" data-ng-options="role.name for role in roles" required=""></select>
</body>
Your Plunkr has errors. You have to define $scope.user = {}; before you use it. Then it will work.
Note: This will only set an initial value to model. If you want to make Administrator highlighted by default, you'll have to figure out some other way.
I am trying to implement http://silviomoreto.github.io/bootstrap-select/ to my AngularJS application.
Most of the people who try and do the same, they have any issue that the selectpicker is set before Angular gets the data. But for me that is not the case. When Select Picker is fired, my select has all the data but for some reason the dropdown toggle event is not firing.
HTML:
<select id="partyRole" name="partyRole" class="form-control" ng-model="partyRole" ng-options="role as role.text for role in partyRoles">
<option value="">Please Select...</option>
</select>
The JS calls adds selectpicker to all my selects.
JS:
$(window).bind("load", function () {
return $('select').selectpicker();
});
I am also using this directive to bind the selectpicker data:
https://github.com/joaoneto/angular-bootstrap-select/blob/master/build/angular-bootstrap-select.js
Final UI
As you can see the div gets created from the selectpicker and I also get all the data.. But clicking on the button does nothing.
I have Angular UI, Angular JS in the application with Bootstrap stylesheets.
EDIT:
Nevermind, the version of the angular directive I downloaded from github was probably in a broken state, because after I applied it from today's updated code.. it worked.
You don't want to have have some jQuery in a file and some AngularJS in another file, usually. If jQuery creates elements etc, they probably won't be picked up by angular.
The correct solution is to use an Angular directive. Here, it looks like somebody made one for you.
function Selectpicker() {
return {
restrict: 'C',
link: function($scope, $element) {
$element.selectpicker();
}
};
}
I´m using Kendo multiselect with Angular-Kendo directives and with remote datasource. I´m trying to set the selected items when the application starts but with no luck. Can anyone please help me?
See Code here: JS Bin
You can just make a custom directive, and pass in the items you want selected beforehand to the value attribute of the multiselect directive, have a look at this Plunk to see the directive I use.
You have to hook into the on change event directive and send the kendoEvent. Then you can use the supported kendo methods on e.sender. Check it out on this plunker
<select id="required" multiple="multiple" kendo-multi-select k-on-change="changed(kendoEvent)">
<option>Steven White</option>
<option>Nancy King</option>
<option>Nancy Davolio</option>
<option>Robert Davolio</option>
<option>Michael Leverling</option>
<option>Andrew Callahan</option>
<option>Michael Suyama</option>
<option selected>Anne King</option>
<option>Laura Peacock</option>
<option>Robert Fuller</option>
<option>Janet White</option>
<option>Nancy Leverling</option>
<option>Robert Buchanan</option>
<option>Margaret Buchanan</option>
<option selected>Andrew Fuller</option>
<option>Anne Davolio</option>
<option>Andrew Suyama</option>
<option>Nige Buchanan</option>
<option>Laura Fuller</option>
</select>
var app = angular.module('app', ['kendo.directives']);
app.controller("myCtrl", function ($compile, $scope) {
$scope.changed = function(e) {
console.log(e.sender.dataItems());
};
});
This sounds simple, but googling is coming up trumps. I have a dropdown select that has multiple categories:
<select ng-model="orderProp" >
<option ng-repeat="cats in categories" value="{{cats}}">{{cats}}</option>
</select>
I also have a map, using Angular Google Maps, which uses JSON data to plot markers. The data for these markers is called $scope.markersProperty
When a users uses the select box, I'd like to dynamically change the value of markersProperty. Using Angular's HTML {{}} I can get the results I want with a simple:
{{markersProperty|filter:orderProp}}
But I can't for the life of me work out how to get similar functionality to update the array $scope.markersProperty. Any ideas?
If you mean you want to update the scope variable, then you can use the $filter service:
.controller('MainCtrl', function ( $scope, $filter ) {
$scope.markersProperty = // ...
$scope.$watch( 'orderProp', function ( val ) {
$scope.filteredMarkersProperty = $filter('filter')($scope.markersProperty, val);
});
});