Get value when selected ng-option changes - angularjs

I have in my .html page a dropdown list,
Dropdown:
<select ng-model="blisterPackTemplateSelected" data-ng-options="blisterPackTemplate as blisterPackTemplate.name for blisterPackTemplate in blisterPackTemplates">
<option value="">Select Account</option>
</select>
I want to execute an action when the user select a value. So In my controller I did:
Controller:
$scope.$watch('blisterPackTemplateSelected', function() {
alert('changed');
console.log($scope.blisterPackTemplateSelected);
});
But the changing the value in the dropdownlist doesn't trigger the code : $scope.$watch('blisterPackTemplateSelected', function()
As a result I tried another method with a : ng_change = 'changedValue()' on the select tag
and
Function:
$scope.changedValue = function() {
console.log($scope.blisterPackTemplateSelected);
}
But the blisterPackTemplateSelected is stored into a child scope. I read that the parent can't get access to the child scope.
What is the correct/best way to execute something when a selected value in a dropdown list changes? If it's method 1, what am I doing wrong with my code?

as Artyom said you need to use ngChange and pass ngModel object as argument to your ngChange function
Example:
<div ng-app="App" >
<div ng-controller="ctrl">
<select ng-model="blisterPackTemplateSelected" ng-change="changedValue(blisterPackTemplateSelected)"
data-ng-options="blisterPackTemplate as blisterPackTemplate.name for blisterPackTemplate in blisterPackTemplates">
<option value="">Select Account</option>
</select>
{{itemList}}
</div>
</div>
js:
function ctrl($scope) {
$scope.itemList = [];
$scope.blisterPackTemplates = [{id:1,name:"a"},{id:2,name:"b"},{id:3,name:"c"}];
$scope.changedValue = function(item) {
$scope.itemList.push(item.name);
}
}
Live example: http://jsfiddle.net/choroshin/9w5XT/4/

I may be late for this but I had somewhat the same problem.
I needed to pass both the id and the name into my model but all the orthodox solutions had me make code on the controller to handle the change.
I macgyvered my way out of it using a filter.
<select
ng-model="selected_id"
ng-options="o.id as o.name for o in options"
ng-change="selected_name=(options|filter:{id:selected_id})[0].name">
</select>
<script>
angular.module("app",[])
.controller("ctrl",['$scope',function($scope){
$scope.options = [
{id:1, name:'Starbuck'},
{id:2, name:'Appolo'},
{id:3, name:'Saul Tigh'},
{id:4, name:'Adama'}
]
}])
</script>
The "trick" is here:
ng-change="selected_name=(options|filter:{id:selected_id})[0].name"
I'm using the built-in filter to retrieve the correct name for the id
Here's a plunkr with a working demo.

Please, use for it ngChange directive.
For example:
<select ng-model="blisterPackTemplateSelected"
ng-options="blisterPackTemplate as blisterPackTemplate.name for blisterPackTemplate in blisterPackTemplates"
ng-change="changeValue(blisterPackTemplateSelected)"/>
And pass your new model value in controller as a parameter:
ng-change="changeValue(blisterPackTemplateSelected)"

Best practise is to create an object (always use a . in ng-model)
In your controller:
var myObj: {
ngModelValue: null
};
and in your template:
<select
ng-model="myObj.ngModelValue"
ng-options="o.id as o.name for o in options">
</select>
Now you can just watch
myObj.ngModelValue
or you can use the ng-change directive like so:
<select
ng-model="myObj.ngModelValue"
ng-options="o.id as o.name for o in options"
ng-change="myChangeCallback()">
</select>
The egghead.io video "The Dot" has a really good overview, as does this very popular stack overflow question: What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

You can pass the ng-model value through the ng-change function as a parameter:
<select
ng-model="blisterPackTemplateSelected"
data-ng-options="blisterPackTemplate as blisterPackTemplate.name for blisterPackTemplate in blisterPackTemplates"
ng-change="changedValue(blisterPackTemplateSelected)">
<option value="">Select Account</option>
</select>
It's a bit difficult to know your scenario without seeing it, but this should work.

You can do something like this
<html ng-app="App" >
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
angular.module("App",[])
.controller("ctrl",['$scope',function($scope){
$scope.changedValue = function(item){
alert(item);
}
}]);
</script>
<div >
<div ng-controller="ctrl">
<select ng-model="blisterPackTemplateSelected" ng-change="changedValue(blisterPackTemplateSelected)" >
<option value="">Select Account</option>
<option value="Add">Add</option>
</select>
</div>
</div>
</html>
instead of add option you should use data-ng-options.I have used Add option for testing purpose

I am late here but I resolved same kind of problem in this way that is simple and easy.
<select ng-model="blisterPackTemplateSelected" ng-change="selectedBlisterPack(blisterPackTemplateSelected)">
<option value="">Select Account</option>
<option ng-repeat="blisterPacks in blisterPackTemplates" value="{{blisterPacks.id}}">{{blisterPacks.name}}</option>
and the function for ng-change is as follows;
$scope.selectedBlisterPack= function (value) {
console.log($scope.blisterPackTemplateSelected);
};

You will get selected option's value and text from list/array by using filter.
editobj.FlagName=(EmployeeStatus|filter:{Value:editobj.Flag})[0].KeyName
<select name="statusSelect"
id="statusSelect"
class="form-control"
ng-model="editobj.Flag"
ng-options="option.Value as option.KeyName for option in EmployeeStatus"
ng-change="editobj.FlagName=(EmployeeStatus|filter:{Value:editobj.Flag})[0].KeyName">
</select>

I had the same issue and found a unique solution. This is not best practice, but it may prove simple/helpful for someone. Just use jquery on the id or class or your select tag and you then have access to both the text and the value in the change function. In my case I'm passing in option values via sails/ejs:
<select id="projectSelector" class="form-control" ng-model="ticket.project.id" ng-change="projectChange(ticket)">
<% _.each(projects, function(project) { %>
<option value="<%= project.id %>"><%= project.title %></option>
<% }) %>
</select>
Then in my Angular controller my ng-change function looks like this:
$scope.projectChange = function($scope) {
$scope.project.title=$("#projectSelector option:selected").text();
};

I have tried some solutions,but here is basic production snippet. Please, pay attention to console output during quality assurance of this snippet.
Mark Up :
<!DOCTYPE html>
<html ng-app="appUp">
<head>
<title>
Angular Select snippet
</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" />
</head>
<body ng-controller="upController">
<div class="container">
<div class="row">
<div class="col-md-4">
</div>
<div class="col-md-3">
<div class="form-group">
<select name="slct" id="slct" class="form-control" ng-model="selBrand" ng-change="Changer(selBrand)" ng-options="brand as brand.name for brand in stock">
<option value="">
Select Brand
</option>
</select>
</div>
<div class="form-group">
<input type="hidden" name="delimiter" value=":" ng-model="delimiter" />
<input type="hidden" name="currency" value="$" ng-model="currency" />
<span>
{{selBrand.name}}{{delimiter}}{{selBrand.price}}{{currency}}
</span>
</div>
</div>
<div class="col-md-4">
</div>
</div>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js">
</script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js">
</script>
<script src="js/ui-bootstrap-tpls-2.5.0.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
Code:
var c = console;
var d = document;
var app = angular.module('appUp',[]).controller('upController',function($scope){
$scope.stock = [{
name:"Adidas",
price:420
},
{
name:"Nike",
price:327
},
{
name:"Clark",
price:725
}
];//data
$scope.Changer = function(){
if($scope.selBrand){
c.log("brand:"+$scope.selBrand.name+",price:"+$scope.selBrand.price);
$scope.currency = "$";
$scope.delimiter = ":";
}
else{
$scope.currency = "";
$scope.delimiter = "";
c.clear();
}
}; // onchange handler
});
Explanation:
important point here is null check of the changed value, i.e. if value is 'undefined' or 'null' we should to handle this situation.

Related

How to use a select menu for user registration in AngularJS?

My current code:
<select ng-model="user.userType" ng-required="true" class="form-control">
<option value="pharmacist">Pharmacist</option>
<option value="chief_pharmacist">Chief Pharmacist</option>
<option value="doctor">Doctor</option>
</select>
//sample code
I need 3 user types to be in the select menu and to pass the selected value to the database.
This might help you, I have listed two ways to achieve this, also have mentioned what value you should pass (I prefer passing id rather than name):
Plnkr
You need to use an angular controller with your view, like this.
var myApp = angular.module('myApp', []);
myApp.controller('MyController', ['$scope', function($scope){
$scope.user = {};
$scope.registerUser = function(){
alert($scope.user.userType);
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyController">
<select ng-model="user.userType" ng-required="true" class="form-control">
<option value="pharmacist">Pharmacist</option>
<option value="chief_pharmacist">Chief Pharmacist</option>
<option value="doctor">Doctor</option>
</select>
<button ng-click="registerUser()">register</button>
</div>
</div>

How to pass an object to the value property in option tag using angular?

I have a select tag which i have loaded the data through angular ng-repeat.
<select ng-model="user.accessRole">
<option ng-selected="{{item.name == user.accessRole.name}}"
ng-repeat="item in accessRoles" value="{{item}}">
{{item.name}}
</option>
</select>
Once I submit this the value I got for accessRole model is as below.
accessRole:"{"id":1,"name":"admin","accessRights":"administrative access"}"
I want this value to be passed without double quotes. That means,
accessRole:{"id":1,"name":"admin","accessRights":"administrative access"}
I tried out this by removing double quotes in value property.(value={{item}})
But it didn't give me the solution.
How can i do this?
It should be like to this.
var app = angular.module('anApp', []);
app.controller('ctrl', function($scope) {
$scope.user = {};
$scope.accessRoles= [{"id":1,"name":"admin","accessRights":"administrative access"}];
$scope.display = function(){
console.log($scope.user);
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
<div ng-app="anApp" ng-controller="ctrl">
<div class="form-group">
<select ng-options="role as role.name for role in accessRoles" ng-model="user.accessRole" ng-change="display()">
</select>
</div>
</div>
use JSON.parse() to convert string to json object
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.user = {};
$scope.accessRoles= [{"id":1,"name":"admin","accessRights":"administrative access"}]
$scope.submit = function(){
console.log($scope.user)
$scope.user.accessRole = JSON.parse( $scope.user.accessRole)
console.log($scope.user)
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<select ng-model="user.accessRole">
<option ng-repeat="item in accessRoles" value="{{item}}">
{{item.name}}
</option>
</select>
<button ng-click="submit()">click</button>
</div>

How to write an attribute value along with ngModel

How to put some additional value with ngModel
If I have an html
<select ng-model="forms.options" data-custom-select="">
<option value="value1" data-special-value="reference1">Value 1</option>
<option value="value2" data-special-value="reference2">Value 2</option>
<option value="value3" data-special-value="reference3">Value 3</option>
</select>
and a custom directive "customSelect" with requires ngModel
I'm expecting a value on ngModel
{value:<Selected Value>,reference:<data-special-value>}
Is this really possible?
You can add the object directly into ng-options and get your result in the selected modal.
using ng-options:
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<select ng-model="selectedName" ng-options="option.value for option in options" ng-change="selected(option.reference)">
</select><br>
Selected Value: {{selectedName}}
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.options = [
{ value: 'value1', reference: 'reference1' },
{ value: 'value2', reference: 'reference2' },
{ value: 'value3', reference: 'reference3' },
]
});
</script>
<p>Select a value from dropdown.</p>
</body>
</html>
Please run the above snippet
HERE IS A WORKING DEMO

ng-select gives only string, but I want an integer

This is my angular html file code. In my mongo database frequencyType added as frequencyType = "1", but I want frequencyType = NumberInt(1);
<div class="span4">
<select class="span12 combobox" ng-model="frequencyType" required>
<option value="1">Daily</option>
<option value="2">Weekly</option>
<option value="3">Monthly</option>
<option value="4">Yearly</option>
</select>
</div>
I get in my database frequencyType = "1" but I want frequencyType = NumberInt(1).
There is an easier way:
Just use value*1 as your id, that will convert the string to int without changing the value... assuming the id is an integer.
so the result is>
<div ng-app ng-controller="MyCtrl">
<select ng-model="selectedItem" ng-options="selectedItem*1 as selectedItem for selectedItem in values"></select>
selectedItem: {{selectedItem}}
</div>
This will work in more cases, since indexOf is not available in objects, only in arrays. This solution works for objects with integers as keys (for example if some keys are missing, or if you use db ids)
Most solutions discussed here require using the ngOptions directive instead of using static <option> elements in the HTML code, as was the case in the OP's code.
Angular 1.6.x
Edit If you use Angular 1.6.x, just use the ng-value directive and it will work as expected.
angular.module('nonStringSelect', [])
.run(function($rootScope) {
$rootScope.model = { id: 2 };
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"></script>
<div ng-app="nonStringSelect">
<select ng-model="model.id">
<option ng-value="0">Zero</option>
<option ng-value="1">One</option>
<option ng-value="2">Two</option>
</select>
{{ model }}
</div>
Older versions
There is a way to make it work while still using static elements. It's shown in the AngularJS select directive documentation.
The idea is to use a directive to register a parser and a formatter on the model. The parser will do the string-to-int conversion when the item is selected, while the formatter will do the int-to-string conversion when the model changes.
Code below (taken directly from the AngularJS documentation page, credit not mine).
https://code.angularjs.org/1.4.6/docs/api/ng/directive/select#binding-select-to-a-non-string-value-via-ngmodel-parsing-formatting
angular.module('nonStringSelect', [])
.run(function($rootScope) {
$rootScope.model = { id: 2 };
})
.directive('convertToNumber', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(val) {
return parseInt(val, 10);
});
ngModel.$formatters.push(function(val) {
return '' + val;
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="nonStringSelect">
<select ng-model="model.id" convert-to-number>
<option value="0">Zero</option>
<option value="1">One</option>
<option value="2">Two</option>
</select>
{{ model }}
</div>
I've just had the same problem and figured out the right way to do this - no 'magic' required. :)
function MyCtrl($scope) {
$scope.values = [
{name : "Daily", id : 1},
{name : "Weekly", id : 2},
{name : "Monthly", id : 3},
{name : "Yearly", id : 4}];
$scope.selectedItem = $scope.values[0].id;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
<div ng-app ng-controller="MyCtrl">
<select ng-model="selectedItem" ng-options="selectedItem.id as selectedItem.name for selectedItem in values"></select>
selectedItem: {{selectedItem}}
</div>
I think the angular way to do this is to use the directive "convert-to-number" in the select tag.
<select class="span12 combobox" ng-model="frequencyType" required convert-to-number>
<option value="1">Daily</option>
<option value="2">Weekly</option>
<option value="3">Monthly</option>
<option value="4">Yearly</option>
</select>
You can see the documentation and a fiddle here at the end of the page : https://docs.angularjs.org/api/ng/directive/select
I suggest you to try to use indexOf.
JS
function MyCtrl($scope) {
$scope.values = ["Daily","Weekly","Monthly","Yearly"];
$scope.selectedItem = 0;
}
HTML
<div ng-app ng-controller="MyCtrl">
<select ng-model="selectedItem" ng-options="values.indexOf(selectedItem) as selectedItem for selectedItem in values"></select>
selectedItem: {{selectedItem}}
</div>
Demo Fiddle
So send to mongoDB $scope.selectedItem value
This is the easiest way I have found so far:
function Controller($scope) {
$scope.options = {
"First option" : 1,
"Second option" : 2,
"Last option" : 10
}
$scope.myoption = 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="Controller">
<select ng-model="myoption" ng-options="label for (label, value) in options"></select>
Option Selected: {{myoption}}
</div>
Or, if you want to use numeric indexes:
function Controller($scope) {
$scope.options = {
1 : "First option",
2 : "Second option",
10 : "Last option"
}
$scope.myoption = 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="Controller">
<select ng-model="myoption" ng-options="value*1 as label for (value, label) in options"></select>
Option Selected: {{myoption}}
</div>
For Angular 2, follow the rabit...

How can I replace a checkbox with a <select> in AngularJS?

My code is set up to allow a user to select a sort direction:
<tr data-ng-repeat="row in gdata | orderBy:inverse">
Here's my HTML:
<div class="orderby">
<div class="arrow up"></div>
<div class="arrow down"></div>
<input type="checkbox" data-ng-model="inverse">
</div>
How can I replace this with a in Angular? So far I have coded this:
<select data-ng-model="inverse">
<option value="??">Sort Up</option>
<option value="??">Sort Down</option>
</select>
Can someone tell me am I doing it the right way and how can I set the values ?
Alot depends on the data you are using, and how you want the user to sort, but I created a basic example in this jsFiddle that you can play around with: http://jsfiddle.net/xRkhc/2/
HTML:
<div ng-controller="MyCtrl">
<div ng-repeat="row in gdata | orderBy:sort">
{{row.model}}
</div>
<select ng-model="sort">
<option value="model">Sort Up by Model</option>
<option value="-model">Sort Down by Model</option>
<option value="topSpeed">Sort Up by TopSpeed</option>
<option value="-topSpeed">Sort Down by TopSpeed</option>
</select>
</div>
Controller:
function MyCtrl($scope) {
$scope.sort = "model"; //just to set the default sort in the dropdown, not required
$scope.gdata = [{'model':'M3','topSpeed':'200'},{'model':'Type R','topSpeed':'150'}, {'model':'S2000','topSpeed':'160'},{'model':'NSX','topSpeed':'180'}];
}
When you hardcode the options (as in your code) the model only receives strings or numbers, you must use ng-options (or it's equivalent data-ng-options) instead of hardcoding the options. You specify the options as a member of your model.
Here's a complete example:
<!doctype html>
<html data-ng-app>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<script>
var exampleCtrl = function ($scope) {
$scope.sortingDirection = {
'Sort Up' : true,
'Sort Down' : false
};
$scope.inverse = true;
}
</script>
</head>
<body>
<div data-ng-controller="exampleCtrl">
<select data-ng-model="inverse" data-ng-options="value as key for (key, value) in sortingDirection">
</select>
<pre data-ng-bind="inverse | json"></pre>
</div>
</body>
</html>

Resources