mles mles - 3 months ago 7
AngularJS Question

Using ng-repeat with ng-model modifies wrong object

TLDR: Here's a plnkr of the issue: https://plnkr.co/edit/HfRoCgPfdoZNxmTtDLf7?p=preview

I have a form with checkboxes:

<div class="form-group">
<div class="input-group">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="rental.car2go.airport.berlin"> Berlin
</label>
<br/>
<label>
<input type="checkbox" ng-model="rental.car2go.airport.hamburg"> Hamburg
</label>
<br/>
</div>
</div>
</div>


that is modifying the rental object. This is how the controller looks like:

angular.module('c2gyoApp', []).controller('c2gyoAppController', [
'$scope',
'state',
function($scope, state) {
$scope.airports = [{
"name": "Berlin",
"model": "rental.car2go.airport.berlin"
}, {
"name": "Hamburg",
"model": "rental.car2go.airport.hamburg"
}, ];

$scope.rental = state.rental;

}]).factory('state', function() {

var rental = {
car2go: {
airport: {
berlin: false,
hamburg: false
}
}
};

return {
rental: rental
};
});


Now I want to use ng-repeat:

<div class="form-group">
<div class="input-group">
<div class="checkbox">
<span ng-repeat="airport in airports">
<label>
<input type="checkbox"
ng-model="airport.model">
{{airport.name}}
</label>
<br>
</span>
</div>
</div>
</div>


With ng-repeat the form is modifying the airports object (
airports[1].model=true/false
and
airports[2].model=true/false
).

It should only use the string of that airport object(
rental.car2go.airport.berlin
and
rental.car2go.airport.hamburg
) and modify the rental object. I'm looking for a way to pass the string to ng-model, not the airports object. How can I do this?

Edit: removed the directive, new plnkr

Answer

Indeed as @Claies suggested I had to copy the value to the rental array. I used a ng-change function for that. New ng-repeat:

<span ng-repeat="airport in airports">
  <label>
    <input type="checkbox"
           ng-model="airport.model"
           ng-change="changeAirport(airport)">
    {{airport.name}}
  </label>
  <br>
</span>

In the controller:

$scope.changeAirport = function(airport) {
  var airportName = $filter('lowercase')(airport.name);
  state.rental.car2go.airport[airportName] = airport.model;
}
Comments