Search code examples
angularjsdrop-down-menuangular-ngmodel

AngularJS combo box selection is not updating model


I am getting an array by AJAX, which looks like this

$scope.eventNameData
Array[2]
    0: Object event_id: "1"title: "Event one" __proto__: Object
    1: Object event_id: "2"title: "Event two" __proto__: Objectlength:     
2__proto__: Array[0]

So, an array of JSON, with each entry having an event_id and a title.

I want to display a drop down combo box with each of the titles, and store the user selected event_id in $scope.selectedEventId

My HTML is

  <select ng-model="analyticEvent" ng-options="x.title for x in eventNameData"
          ng-change="SelectedAnalyticEventChanged()">
  </select>

I initialize the model, when I receive the JSON data, with

                if (! $scope.eventNameData)
                    return;

                if ($scope.selectedEventId == -1)
                {
                    $scope.selectedEventId = $scope.eventNameData[0]['event_id'];
                    $scope.analyticEvent = $scope.eventNameData[0];
                }

and handle the selection changing with

$scope.SelectedAnalyticEventChanged = function()
{
    $scope.selectedEventId = $scope.analyticEvent.event_id;
}

but, when I breakpoint that, the value of the model, $scope.analyticEvent never changes.

HOWEVER, when I add analyticEvent == {{analyticEvent}} to my HTML, just before the combo box, that is updated when I select from the combo box.

What am I doing wrongly? How do I get the value of the event_id of the selected object into $scope.selectedEventId?


[Update] Googling, I see some remarks about child scope - could that be it?


[Update++] I think I should stress more that if display {{selectedEventId}} in my HTML, then it is getting updated correctly - even though it doesn't get updated in the ng-change function - how can that be?


Solution

  • Aha! It was a child scope problem.

    Change the html to

    <select ng-model="analyticEvent.data" ng-options="event as event.title 
            for event in eventNameData"   ng-change="SelectedAnalyticEventChanged()">
    </select>
    

    and the intialzation code to

    $scope.analyticEventDummyData = {"event_id" : -1,
                                     "title" : ''};
    $scope.analyticEvent = {"data" : $scope.analyticEventDummyData};
    

    at the start of the controller, and do this when the JSON is received

                    if (! $scope.eventNameData)
                        return;
    
                    if ($scope.selectedEventId == -1)
                    {
                        $scope.selectedEventId = $scope.eventNameData[0]['event_id'];
                        $scope.analyticEvent.data = $scope.eventNameData[0];
                    }
    

    and the ng-change code becomes

    $scope.SelectedAnalyticEventChanged = function()
    {
        $scope.selectedEventId = $scope.analyticEvent.data.event_id;
    }
    

    and we see the correct value in that function:

    $scope.analyticEvent.data
    "object:39"  
        event_id: "2"
        title: "Event two"
       __proto__: Object
    

    Quod erat demomstrandum :-)