Cannot bind ngResource to ngOptions - angularjs

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

Related

Initial value of select not set in AngularJS

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

How to set a default value to ng-options (multiple select)

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.

angularjs ng-paste not updating model value

I have used ng-paste for textarea while pasting the link in textarea, i am calling a custom function to store that value. Please refer following code
<textarea rows="1" ng-model="myObj.content"
ng-paste="getContent(myObj)">
</textarea>
$scope.getContent = function(a){
console.log(a.content);
}
But in console always I am getting undefined value. How can I get my object value?
Passing model to function does not really make sense since you have already specified ng-model, so it's value will be updated as user types something into the textbox. If you want to track changes you can setup a $watch for your model or specify a function using ng-change.
If you want to know what user pasted, then that's another story. Handling ng-paste can be tricky. To access the actual event, easiest is to include jQuery before angularjs and then do e.g. following:
HTML template
<textarea rows="3"
placeholder="copy/paste here..."
ng-init="content = null"
ng-model="content"
ng-paste="paste($event.originalEvent)">
</textarea>
Controller
$scope.paste = function (event) {
var item = event.clipboardData.items[0];
item.getAsString(function (data) {
console.log(data);
});
};
Related plunker here http://plnkr.co/edit/ea5y5j
Simply use $timeout to call your paste callback after the model has been updated.
$scope.getContent = function(a){
$timeout(function () {console.log(a.content)});
}

AngularJS calculated ng-model

I have following controller.
app.controller("testCtrl", function(){
$scope.utcTime = 1380150771;
$scope.parseTime = function(t){
//return local time string
}
});
In the view, I have
<input type="text" ng-model="parseTime(utcTime)" />
Its not working. Can I bind ng-model to a method that returns the string ?
Any alternative way to show the value in the input button ?
You can use ngChange and ngModel both
JS
$scope.utcTime = 1380150771;
$scope.parseTime = function(){
console.log($scope.utcTime);
//return local time string
}
HTML
<input type="text" ng-change="parseTime()" ng-model="utcTime" />
ng-model is mapping through tag and controller.
At first you can see default utcTime (1380150771) that you assign in input tag.
And when you change the text in input tag, ng-model(utcTime) will be changed automatically in the controller.
Then each letter that you typed will call ng-change(parseTime) function.
You can check by console.log method.
My solution is based on this source:
https://groups.google.com/forum/#!topic/angular/1mnra0vamtg
I have edited the Plunker sample code to use ng-value to generate and update ng-model using calculation function. See this link below:
http://plnkr.co/edit/Fmqw0wp37Ndk1yuWvFkV?p=preview
Also, the above sample shows you how you format the result for display using custom filter.
In other posts, some have suggested using $watch() to detect change to input variables and update ng-model variable accordingly. Using ng-value is much better than using $watch() since the latter forces you to include all input variables in the watch which may be impossible if you have very complex calculation model.
Tarek
Try doing this
app.controller("testCtrl", function(){
$scope.utcTime = 1380150771;
$scope.result= $scope.parseTime( $scope.utcTime)
$scope.parseTime = function(t){
//return local time string
}
});
html
<input type="text" ng-model="result" />
Yes you can try follwing:
its working example:
<input type="text" ng-model="parseTime(utcTime)" />
app.controller("testCtrl", function(){
$scope.utcTime = 1380150771;
$scope.parseTime = function(t){
//return local time string
new Date(t).toISOString();
}
});

Angular.js - Using a filter to alter a variable

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);
});
});

Resources