Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS select ng-change function not finding selected model

I'm having trouble with some basic angular databinding.

my view:

<select
    ng-model="selectedPerson"
    ng-options="person.name for person in testdataset"
    ng-change="personChanged(selectedPerson)">
    <option value="">All Persons</option>
</select>

my controller:

$scope.testdataset = [
    {name:"bill"},
    {name:"bob"},
    {name:"batman"}
];
$scope.personChanged = function(person) {
    console.log(person);
}

This works great--selected name is logged.

But this simply prints "undefined" when a name is selected

view:

<select
    ng-model="selectedPerson"
    ng-options="person.name for person in testdataset"
    ng-change="personChanged()">
    <option value="">All Persons</option>
</select>

controller:

$scope.testdataset = [
    {name:"bill"},
    {name:"bob"},
    {name:"batman"}
];
$scope.personChanged = function() {
    console.log($scope.selectedPerson);
}

I'm new to angular, and I'm just perplexed. I'm assuming it's got to do with the, er, "scope" of $scope inside the function, but I'm not sure how to troubleshoot...

like image 207
snuggles Avatar asked Nov 30 '13 00:11

snuggles


1 Answers

It was mentioned in the comments already, but your selectedPerson is a member on A scope. Not nessisarily the scope of the controller ($scope). Depending on the rest of your page/application, the selectedPerson could be on a different scope. Say you use a ng-repeat outside/above (as a parent to your code displayed), then the selectedPerson will live as a member of that scope, NOT the scope of the controller.

The way scopes work is pretty straightforward though as it inherits from its parents. If you place something on the scope of the controller - it will be the outmost scope of that controller (the part of your html marked ng-controller) unless ofcourse that you have already nested that part inside another controller. Finally there is $rootScope which would the real out-most scope from which every other scope inherits from.

<div ng-controller="MainController">
    <div ng-repeat="item in items"> <!-- **This creates a new nested scope** -->
        <select ng-model="selectedPerson" ng-options="...">
        </select>
    </div>
</div>

Using the above template, whatever you put on $scope in your controller can be read in both the inner div and the select itself. The ng-model though can not be directly read in the controller though.

If you do this in your controller:

app.Controllers('MainController', function ($scope) {
  $scope.selectedPerson = {};
});

Then you will create a object on the outer scope and your ng-model will inherit and reference that same object. Beware though, that for each select inside your ng-repeat will be using the SAME selectedPerson.

I hope this explains why?

like image 68
Per Hornshøj-Schierbeck Avatar answered Nov 02 '22 19:11

Per Hornshøj-Schierbeck