Search code examples
javascriptangularjsjsonangularjs-ng-repeatangularjs-material

ng-model within ng-repeat not updating reference object


In my controller, I have an object:

$scope.selectedMap = {
    map: '', mapDesc: '', stops_json: "", stopLength: []
};

The stops_json key in this object holds another object, that looks like this:

{
  desc: "PRG-BUD-HR-PAY",
  stop1:"DEPT",
  stop2:"ACCT",
  stop3:"ACCT2",
  stop4: 158,
  stop5:"CCT",
  stop6:"CCA",
  stop7: 156
}

I'm using this child object in an ng-repeat, and generating inputs with it for each stop:

<p class="row col-md-12">
  <strong>Description:&nbsp;</strong>{{ selectedMap.stops_json.desc }}
</p>
<div class="row col-md-12 float-left">
    <md-input-container ng-repeat="stop in selectedMap.stops_json" ng-if="!$first" ng-model="stop" class="col-md-12">
        <label>Stop&nbsp;{{ $index }}:</label>
        <input class="col-md-8 float-left mapStops" ng-model="stop" aria-label="Route Stop Description">
    </md-input-container>
</div>

My issue is, that when I change the value of the input tags, the stops_json object does not change. I was under the impression that it was supposed to, since that is the object that is modeled. I am clearly mistaken, can anyone educate me?


Solution

  • A few problems to mention first:

    • The notation for iterating over objects with ng-repeat is (key, value) in obj
    • If you choose to use object iteration with ng-repeat then your ng-if dependent on $first is non-deterministic (i.e. iterating in key definition order is not guaranteed)
    • Applying an ng-model binding on the ng-repeat with the intention of making its constituents editable is incorrect—the models of each item should be have ng-model applied instead

    I've created a stripped down example of your snippet to demonstrate making the repeated inputs able to change the stops_json model.

    See here.

    Basically, you need to ensure the input elements inside the ng-repeat directly bind to your stops_json model in order for any edits to affect it.

    Also, note that all any numeric properties should use the type="number" variant of input, otherwise any edits will set the values to strings instead.