116

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?

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
xiaolong97427
  • 1,163
  • 2
  • 7
  • 5

10 Answers10

191

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/

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
Alex Choroshin
  • 6,177
  • 2
  • 28
  • 36
  • hi, great answer. here the value of option set as whole row details of item. how can i set it to id? – AmiLinn Jun 18 '18 at 07:21
  • hi @Alex Choroshin i have same type of problem but i am getting data from database when i collect data from database how to show that data in a div ? i try this in controller's function $scope.accountdetaildata = data.data; and in views div i try this code {{accountdetaildata .balance}} but data not shown there as data received from database and i can see that data in console – Nadeem Ijaz Aug 23 '18 at 11:20
  • Thanks - how does this work? Seems like hocus pocus. The variable `blisterPackTemplateSelected` is never declared - is angular just inferring it? – Adam Hughes May 01 '23 at 16:04
34

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.

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
simon
  • 526
  • 4
  • 8
20

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)"
Artyom Pranovich
  • 6,814
  • 8
  • 41
  • 60
8

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?

Community
  • 1
  • 1
Martijn Welker
  • 5,575
  • 1
  • 16
  • 26
5

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.

Wawy
  • 6,259
  • 2
  • 23
  • 23
3

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

    };
Usman
  • 2,547
  • 31
  • 35
2

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

Saurabh
  • 7,525
  • 4
  • 45
  • 46
1

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>
Rahul Modi
  • 748
  • 11
  • 21
0

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();
     };
edencorbin
  • 2,569
  • 5
  • 29
  • 44
0

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.

Kirill Shur
  • 280
  • 2
  • 4