Get value when selected ng-option changes

AngularjsAngularjs Scope

Angularjs Problem Overview


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?

Angularjs Solutions


Solution 1 - Angularjs

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/

Solution 2 - Angularjs

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.

Solution 3 - Angularjs

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)"

Solution 4 - Angularjs

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?

Solution 5 - 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.

Solution 6 - Angularjs

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

Solution 7 - Angularjs

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

    };

Solution 8 - Angularjs

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>

Solution 9 - Angularjs

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

Solution 10 - Angularjs

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionxiaolong97427View Question on Stackoverflow
Solution 1 - AngularjsAlex ChoroshinView Answer on Stackoverflow
Solution 2 - AngularjssimonView Answer on Stackoverflow
Solution 3 - AngularjsArtyom PranovichView Answer on Stackoverflow
Solution 4 - AngularjsMartijn WelkerView Answer on Stackoverflow
Solution 5 - AngularjsWawyView Answer on Stackoverflow
Solution 6 - AngularjsSaurabhView Answer on Stackoverflow
Solution 7 - AngularjsUsmanView Answer on Stackoverflow
Solution 8 - AngularjsRahul ModiView Answer on Stackoverflow
Solution 9 - AngularjsedencorbinView Answer on Stackoverflow
Solution 10 - AngularjsKirill ShurView Answer on Stackoverflow