Track option in select based on a specific property - angularjs

I am diving directly on my problem:
On controller:
$scope.code = 1
$scope.codes [
{
"1":"Accepted"
"0":"Rejected"
}
On view:
<select ng-model="code" ng-options="key as value for (key,value) in codes track by key"></select>
Is there any way to have "Accepted" selected on my view ? I know that the $scope.code is not an object but I want to assign it the value passed by selected option (key).
For anyone who would like to reproduce my problem, I got a plunk made.

You are almost there, you just need to do minor changes:
Remove the track by statement like this:
<select ng-model="myVal" ng-options="key as val for (key,val) in data"></select>
And in $scope.myVal set the value as string because you are assigning an integer.
And that should work.

Related

Angular JS : ng-option add "string:" prefix int the option value

Below is my select with ng-options:
<select ng-options="key as value for (key , value) in getList() ..."> </select>
The getList() function retrieves the following object:
{"CURRENT_ACCOUNT":"test1","ORDINARY_ACCOUNT":"test2"}
and if I inspect the generated options, it is the following:
<option label="test1" value="string:CURRENT_ACCOUNT" selected="selected">test1</option>
As you can see, everything seems right except the value attribute has a string: prefix.
How can I remove the prefix? What did I do wrong?
You didn't do anything wrong and your code is actually correct. This is how AngularJS creates the options.
<select ng-model="selected" ng-options="key as value for (key, value) in getList()"></select>
Selected: {{selected}}
If you print out the value of the selected item immediately following it, you'll noticed that the value is just CURRENT_ACCOUNT and not string:CURRENT_ACCOUNT as the option leads you to believe.
Here is a plunker demonstrating it.
https://next.plnkr.co/edit/lvEi6pknJZMh0wab?open=lib%2Fscript.js&deferRun=1

ngOptions successfully refreshes with new values, but ng-model is not data-binding

I have 2 select forms populated using ng-options, such as:
<select ng-options="item.id as product.category for product in products" ng-model="order.category" ng-change='find_brands(order.category)' ></select>
<select ng-options="brand.id as brand.name for brand in brands" ng-model="order.brand" ></select>
<button ng-click='Get_Products(order)>ORDER</button>
When the first dropdown is selected, it will trigger a $http call to populate the second dropdown like so:
$scope.find_brands = function(category){
$http
.get('Default.aspx/Find_Brands', {category: category})
.success(data){$scope.products = data.d};
};
This correctly populates the "brands" dropdown with the new values. However, when I go to select a brand, the ng-model does not change. When tested, I receive a null value. I've looked into $scope.$apply to work with the $digest cycle, but it seems like that is not my problem (the "brands" dropdown successfully gets refreshed data, it just doesn't SEND data out).
Does anyone have an idea of whats going on and how to fix it?
I've been creating this simple example for you: http://jsbin.com/degece/edit?html,js,console,output
In your code there are some errors.
In this line you use item.id instead product.id
<select ng-options="item.id as product.category for product in products" ng-model="order.category" ng-change='find_brands(order.category)' ></select>
In this you have a quote typo, you don't need the quote before Get_Products
<button ng-click='Get_Products(order)>ORDER</button>
Finally, here you need to assign the result of the call to the $scope.brands variable
.success(data){$scope.products = data.d};
In my example you can see some best practice implementations like the model initialization.

ng-change get new value and original value

I'm using ng-options to select values from a pulldown. I'd like to be able to compare the old value to the new value. ng-change works well for grabbing the new value of the pull down, but how can I get both the new value and the original value?
<select ng-change="updateValue(user)" ng-model="user.id" ng-options="user.id as user.name for user in users"></select>
For instance, let's say I wanted the controller to log, "Your former user.name was BILL, your current user name is PHILLIPE."
With an angular {{expression}} you can add the old user or user.id value to the ng-change attribute as a literal string:
<select ng-change="updateValue(user, '{{user.id}}')"
ng-model="user.id" ng-options="user.id as user.name for user in users">
</select>
On ngChange, the 1st argument to updateValue will be the new user value, the 2nd argument will be the literal that was formed when the select-tag was last updated by angular, with the old user.id value.
Also you can use
<select ng-change="updateValue(user, oldValue)"
ng-init="oldValue=0"
ng-focus="oldValue=user.id"
ng-model="user.id" ng-options="user.id as user.name for user in users">
</select>
You can use something like ng-change=someMethod({{user.id}}).
By keeping your value in side {{expression}} it will evaluate expression in-line and gives you current value(value before ng-change method is called).
<select ng-model="selectedValue" ng-change="change(selectedValue, '{{selectedValue}}')">
Just keep a currentValue variable in your controller that you update on every change. You can then compare that to the new value every time before you update it.'
The idea of using a watch is good as well, but I think a simple variable is the simplest and most logical solution.
You can use a scope watch:
$scope.$watch('user', function(newValue, oldValue) {
// access new and old value here
console.log("Your former user.name was "+oldValue.name+", you're current user name is "+newValue.name+".");
});
https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch
You could use a watch instead, because that has the old and new value, but then you're adding to the digest cycle.
I'd just keep a second variable in the controller and set that.
You can always do:
... ng-model="file.PLIK_STATUS" ng-change="file.PLIK_STATUS = setFileStatus(file.PLIK_ID,file.PLIK_STATUS,'{{file.PLIK_STATUS}}')" ...
and in controller:
$scope.setFileStatus = function (plik_id, new_status, old_status) {
var answer = confirm('Czy na pewno zmienić status dla pliku ?');
if (answer) {
podasysService.setFileStatus(plik_id, new_status).then(function (result) {
return new_status;
});
}else{
return old_status;
}
};

Programmatically selecting ng-options bound to object data source

I have an ng-options select bound to an object. Setting the ng-model programmatically only works properly (updates the select) when setting it as a string. If I set the ng-model as an integer, it doesn't work. I really don't want to have to make this conversion. Is this the only way?
http://jsfiddle.net/HMjnV/1/
<div ng-controller="MyCtrl">
<select ng-options="id as name for (id, name) in items" ng-model="selected"></select>
<div>Selected ID: {{selected}} </div>
<button ng-click="setSelected(1)">Set Selected to ID 1 as Integer</button>
<button ng-click="setSelected('1')">Set Selected to ID 1 as String</button>
<div>Programmatically setting the ng-model as string sets the dropdown but not as integer.</div>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.items = {1: 'a', 2: 'b', 3:'c'};
$scope.selected = null;
$scope.setSelected = function(id) {
$scope.selected = id;
}
}
EDITED
You might try using toString when you programmatically set the model value, if you're looking for a quick and dirty solution. See #ExpertSystems answer for detail on the core of the problem.
$scope.setSelected = function(id) {
$scope.selected = id.toString();
}
This is odd, but you can get the binding between ng-options and ng-model to work by forcing a cast to occur in the comprehension expression:
ng-options="id*1 as name for (id, name) in items"
Here is a fork of your fiddle demonstrating this trick: http://jsfiddle.net/wittwerj/HMjnV/9/
Having said that, I do prefer Marc's approach of converting toString in the controller.
Yes to pre-populate the value like you have done then definitely it should be a string. Since the value attribute in option tag takes only String. But yes in AngularJs you can give references like this given in the fiddle . And the workaround to your problem will be converting id to string.
JS Objects have property name-value pairs.
value can be of any type, but name is always a string.
Although you think you define it as a number, it is automatically converted to string.
There is no way you can change that (i.e. create an object with number property-names).

How can I detect when a USER changes the value in a select drop down using AngularJS?

I have the following:
<select data-ng-model="selectedTestAccount" data-ng-options="item.Id as item.Name for item in testAccounts">
<option value="">Select Account</option>
</select>
It was suggested to me that I could watch for the value of this select to change with the following:
$scope.$watch('testAccounts', function(){
/* get updated values and update other select "model" on success*/
alert("hello");
});
But this does not seem to work. For one thing it gives an alert as soon as the select appears on the screen and before the user has selected anything. Also am I correct in saying that I should be watching for a change in selectedTestAccount? Finally one more question. How can I show the value of selectedTestAccount in an alert box?
As said, you can get it as the first argument, no need to get it from scope. Use
$scope.$watch('selectedTestAccount', function(newValue){
alert(newValue);
});
Beware that you always get a undefined as the first change for a $watch.
What about putting an "ng-change" to your select?
In your example it would be something like this:
<select data-ng-model="selectedTestAccount" ng-change="updateSelectedAccount(selectedTestAccount)" data-ng-options="item.Id as item.Name for item in testAccounts"></select>
And then in your controller
$scope.updateSelectedAccount = function (selectedTestAccount) {
console.log(selectedTestAccount);
}
P.S. Sorry, just noticed how old this question is :) Hope this might help somebody in the future.

Resources