ng-change get new value and original value - angularjs

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

Related

Track option in select based on a specific property

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.

Default value with ng-options after filter

I have a <select> box with options driven from a filter, based on the value of another field in the model (another <select> field). If, after filtering the list, there's only one option to display, I want to make it the selected option. ng-init seems like a starting point, but it's also recommended by the Angular team as something to not use.
SELECT:
<select
tabindex="5"
class="form-control"
ng-model="vm.transaction.um"
ng-options="um.name for um in vm.ums | measuresForItem:vm.transaction.item">
</select>
Basically what you want to do is to change some model value (vm.transaction.um) based on some other model value (filtered vm.ums). There is $watch() function that does exactly this thing. Try
$scope.$watch('(vm.ums | measuresForItem:vm.transaction.item).length', function(newVal) {
if (newVal == 1)
$scope.vm.transaction.um = (<get filtered result here>)[0].name;
});
Actually ng-init is not that bad for such sort of tasks, but it executes only once, and it might be not suitable for dynamic filters or any kind of deferring.
Just set vm.transaction.um (the member you assigned to ng-model) in your controller:
if(this.vm.ums.length === 1) {
this.vm.transaction.um = this.vm.ums[0];
}

Can't get Angular select to update with selected value

I'm using selects to allow a user to switch between events and years. Each change will pull appropriate data from the server, return and update the page. However, the select box goes from the selected value to an empty value. I've looked at numerous solutions and they aren't working.
<select
ng-model="eventName"
ng-options="item.value for item in eventOptions track by item.value"
ng-change="changeEvent(eventName.value)">
</select>
This is the changeEvent function:
$scope.changeEvent = function(eventName){
$scope.eventName = eventName; //wrongly assumed this would update the selected value
$scope.getData($scope.eventName,$scope.eventYear); //this returns the json - correct
$scope.updateSelected(); //meant to update the select field value on the page - fails
};
$scope.eventName or $scope.eventYear values will properly update on a change, but has no effect on the page. The selects just empty of a selected value.
UPDATED (with corrected code)
I wanted to post the changes I made more clearly than the comment allows.
I removed the object param "value" from the options and the argument from the function call (eventName.value).
<select
ng-model="eventName"
ng-options="item for item in eventOptions track by item"
ng-change="changeEvent()">
</select>
And the changeEvent function gets simplified to:
$scope.changeEvent = function(){
$scope.getData($scope.eventName,$scope.eventYear);
};
It all works as expected! Thanks to all, especially Delta who got me looking at it the right way.
So, your event name variable is set to be item. not item.value so instead of passing in changeEvent(eventName.value) try passing in changeEvent(eventName). either way the value you are passing into your method doesnt match the value of your model's variable
item.value for item in eventOptions track by item.value
so for this statement, you are saying make my options ng-model=item but make their value=item.value so they show what you want them to show but still have all the information you need from each one.
Upon further inspection is looks like you dont need:
$scope.eventName = eventName;
$scope.updateSelected();
Angular should be updating your eventName for you, you just need to call the change method.
I'm not sure you need:
ng-change="changeEvent(eventName.value)"
if you use ng-options the model will be updated in the scope automatically on selection. You could watch the value in the controller if you want to do other stuff when it changes:
$scope.$watch('eventName', function() {
//do stuff
});

How to get option value of select element

I am trying to get the option value of a select element using Protractor. However, I'm not able to find the option element.
HTML
<select ng-options="opions.c as options.n for option in options" ng-model="model">
<option value="0">Option 1</option>
<option value="1">Option 2</option>
</select>
Spec-file
describe('testing select option', function() {
it('', function() {
ptor = protractor.getInstance();
//This will not get the option required
ptor.findElement(protractor.By.binding('model'));
});
});
I cannot seem to find a way to grab the option value as I haven't found a function that I can use that doesn't give and exception or error message.
Does anyone know how to resolve this issue?
I have had some problems getting dropdowns working well, and have spent some time today working it out (and therefore I'm sharing it here in case someone else finds it useful).
On earlier versions of Protractor there was a by.selectedOption, which effectively does the same thing as by.select, but returns only the selected item. So, to get the text of the selected option above, you could have:
expect(element(by.selectedOption('model')).getText()).toEqual('Option 1');
I wrote a blog post if you want more detail, it also covers a helper function for selecting the option in the dropdown: http://technpol.wordpress.com/2013/12/01/protractor-and-dropdowns-validation/
Recent versions of protractor have removed this function, replacing it with:
expect(element(by.id('my_id')).element(by.css('option:checked')).getText();
Which is more flexible, as it can be applied to any of the finders, whereas selectedOption only worked with a model finder.
ok again I have now been able to figure out how to grab the option element with protractor.
the example code below shows how to accomplish this.
ptor.findElement(protractor.By.css('select option:nth-child(value of the option you require IE: the number)')).click();
Try using xPath:
ptor.findElement(protractor.By.xpath('//select/option[1]'));
You can use the same technique to choose an option by value:
protractor.By.xpath('//select/option[text()="Option 2"]'));
I've needed to do this for setting up forms where inputs are visible based on selected dropdowns, e.g.:
makeFord = protractor.By.xpath('//select[#id="make"]/option[text()="Ford"]'));
modelMustang = protractor.By.xpath('//select[#id="model"]/option[text()="Mustang"]'));
makeFord.click();
modelMustang.click();
Here is how you can get the value of an option in a select:
HTML
<select ng-options="opions.c as options.n for option in options" ng-model="model">
<option value="Africa">Option 1</option>
<option value="Switzerland">Option 2</option>
</select>
.spec file
describe("Country <select>", function() {
it("should have 'Africa' as the value of the first option", function() {
browser.get('index.html');
let all_options = element.all(
by.options("opions.c as options.n for option in options") //use whatever string is assigned to the ng-options attribute in the html
);
let first_option = all_options.get(0); //or all_options.first()
let second_option = all_options.get(1); //or all_options.last()
expect(
first_option.getAttribute('value')
).toEqual("Africa");
});
});
To get the value of a selected option (which can be an option programmatically selected with protractor by calling click() on an option):
expect(
element(
by.model('model') //'model' is the string assigned to the select's ng-model attribute
).element(
by.css('option:checked')
).getAttribute('value')
).toEqual('Swizerland');
This will help.
//check whether the selected value is equal to the expected value.
expect(element(by.model("model")).getAttribute('value')).toEqual("0");
//catch the selected value
element(by.model("model")).getAttribute('value').then(function (value) {
console.log('selected value', value);
});
In order to enumerate the option tags you can try to use the .all method and you should access it by the parent first.
element(by.model('model')).all(by.tagName('option')).then(function(arr) {
expect(arr.length).toEqual(2);
});
Have a look at the API reference for inspiration
http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.all
Edit: also follow the style guide which discourages usage of XPath
http://www.protractortest.org/#/style-guide

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