Search code examples
javascriptangularjslocal-storageng-options

Display an object property of local storage in ng-options


In my Angular app, I store victim data in the local storage. In my view, victim data is displayed and we can update it (from <select>):

<h1>Victim #{{victim.numero}}</h1>

<label>Victim status</label>
<select ng-model="victim.status" ng-options="s.libelle for s in status"></select>

<label>Victim situation</label>
<select ng-model="victim.situation" ng-options="s for s in situations"></select>

The problem is that the value stored in victim.status is not displayed by default when refreshing the page (it is not null). The curious point is that is works well for victim.numero and victim.situation.


With the following Fiddle, here is a scenario to see the bug:

  1. Open the Fiddle
  2. status input will be void, although the binded variable is set
  3. Modify it, click "Save changes": it is displayed correctly
  4. Press F5: The variable is correctly updated in local storage, but still not displayed in the input
  5. Note that situation input still works correctly

The only difference between victim.status and victim.situation is that status is an object and situation is a string.


I've made a dummy code to reproduce the issue:

JSFiddle of the code


I want the status input to be default set with victim.status when loading the page, how can I fix it?

Thanks!


Solution

  • The issue is in your ng-options, as your select list is an object try adding track by

     <select ng-model="victim.status" ng-options="s.libelle for s in status track by s.libelle"></select>
    

    JSFiddle of the working code

    The reason you have to use track by is because your array in you select contains objects. This means the html that is produced ends up looking like this.

    <select ng-model="victim.status" ng-options="s.libelle for s in status" class="ng-pristine ng-valid ng-touched">
        <option value="?" selected="selected"></option>
        <option label="Unknown" value="object:3">Unknown</option>
        <option label="Safe" value="object:4">Safe</option>
        <option label="Dead" value="object:5">Dead</option>
    </select>
    

    enter image description here

    As you can see from this your value victim.status doesn't equal object:4.

    What track by does is replaces the value in the value attribute and uses the property of the model instead of the whole model. So you're html comes out like this.

    <select ng-model="victim.status" ng-options="s.libelle for s in status track by s.libelle" class="ng-pristine ng-valid ng-touched">
        <option label="Unknown" value="Unknown" selected="selected">Unknown</option>
        <option label="Safe" value="Safe">Safe</option>
        <option label="Dead" value="Dead">Dead</option>
    </select>
    

    And instead of doing does victim.status === "Safe" it will do victim.status.libelle == "safe"

    I hope this explains it well enough, if you want any more clarification let me know.