user5367575
user5367575

Reputation: 29

Lose repeated value inside ng-options

plunker example

I have some cars and available years for them:

Note: 2008 year is repeated. It's important)

I set 2006 (any year except 2008) year for Volvo by default.
Click "Load car 1", then "Load car 2".
You can see 2006 yet. It works.

But change from 2006 to 2008.
Click "Load car 1", then "Load car 2".
2008 is lost. It doesn't work.

Why? What don't I understand? It doesn't matter type of value for SELECT tag (number or string)


If I remove

//I use length = 0 in ng-disabled to user can't change 'year' while timeout interval
if (main.years) main.years.length = 0;

or $timeout it will work.
I tried to use bind. It didn't work.

Thanks.


I did simple example. But in my project I have a lot of fields and slow client server. And if I choose cars very quickly, data in cars array and options in select are lost

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($timeout) {
  var main = this;

  main.selectCar = selectCar;
  main.models = ["Volvo", "VW", "Audi", "Ford", "Honda", "Jaguar"];
  //main.years = [2006, 2007, 2008, 2009, 2010, 2011];
  main.cars = [{
    year: 2006,
    model: "Volvo"
  }, {
    year: 2011,
    model: "Honda"
  }];

  selectCar(main.cars[0]);

  // bind doesn't work too
  function selectCar(car) {
    // I use length = 0 in ng-disabled to user can't change 'year' while timeout interval
    if (main.years) main.years.length = 0; //will work without this line

    main.activeCar = car;
    getDataFromServer('years');

    console.log(main.cars[0].year);
  }

  function getDataFromServer(nameForOptions) {
    // don't think about this logic
    // $q
    $timeout(function() { //will work without $timeout
      var arr;
      if (nameForOptions === 'years') {
        if (["Volvo", "VW", "Audi"].indexOf(main.activeCar.model) > -1) {
          arr = [2006, 2007, 2008];
        } else {
          arr = [2008, 2009, 2010, 2011];
        };
      }

      main[nameForOptions] = arr;
    }, 100);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<body ng-app="plunker" ng-controller="MainCtrl as main">
  <br /><br />
  <button ng-click="main.selectCar(main.cars[0])">Load car 1</button>
  <button ng-click="main.selectCar(main.cars[1])">Load car 2</button>
  <br /><br />
  <select id="select_1" ng-model="main.activeCar.model" ng-options="model for model in main.models" ng-disabled="!main.models.length"></select>
  <select id="select_2" ng-model="main.activeCar.year" ng-options="year for year in main.years" ng-disabled="!main.years.length"></select>
  <hr />
  <p>Cars:</p>
  <ol>
    <li ng-repeat="car in main.cars">{{car.model}} - {{car.year}}</li>
  </ol>
</body>

Upvotes: 0

Views: 65

Answers (2)

user5367575
user5367575

Reputation: 29

I did it like this plunker fork

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($q, $timeout) {
  var main = this;
  main.selectCar = selectCar;
  
  main.models = ["Volvo", "VW", "Audi", "Ford", "Honda", "Jaguar"];

  main.cars = [
    {
      year: 2006,
      model: "Volvo"
    },
    {
      year: 2011,
      model: "Honda"
    }
  ];
  
  selectCar(main.cars[0]);

  function selectCar(car){
    //I use length = 0 in ng-disabled to user can't change 'year' while timeout interval (wait server response)
    if (main.years) main.years.length = 0;
    
    main.activeCar = {};

    getDataFromServer('years', car).then(function(){
      main.activeCar = car;
      console.log(main.cars);
    });
  }
  
  function getDataFromServer(nameForOptions, car){
    //don't think about this function and logic inside it
    var deferred = $q.defer();

    //wait server response
    $timeout(function(){
      var arr;
      if (nameForOptions === 'years') {
        if (["Volvo", "VW", "Audi"].indexOf(car.model) > -1) {
          arr = [2006, 2007, 2008];
        } else {
          arr = [2008, 2009, 2010, 2011];
        };
      }
      
      main[nameForOptions] = arr;
      
      deferred.resolve();
    }, 100);
    
    return deferred.promise;
  }

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<body ng-app="plunker" ng-controller="MainCtrl as main">
  <br /><br />
  <button ng-click="main.selectCar(main.cars[0])">Load car 1</button>
  <button ng-click="main.selectCar(main.cars[1])">Load car 2</button>
  <br /><br />
  <select id="select_1" ng-model="main.activeCar.model" ng-options="model for model in main.models" ng-disabled="!main.models.length"></select>
  <select id="select_2" ng-model="main.activeCar.year" ng-options="year for year in main.years" ng-disabled="!main.years.length"></select>
  <hr />
  <p>Cars:</p>
  <ol>
    <li ng-repeat="car in main.cars">{{car.model}} - {{car.year}}</li>
  </ol>
</body>

Upvotes: 0

Srinivas Paila
Srinivas Paila

Reputation: 827

Please initialize the activeCar to empty object. main.activeCar = {};

Upvotes: 0

Related Questions