user3738290
user3738290

Reputation: 445

How to data-bind an array element with Angular

I am using Angular.

I have a table with two columns. Each cell of 1st column is a series number. Each cell of second column is a drop down of serial numbers. I am binding to a data source in my component and it is working fine.

My data source is a simple hard coded array in my component (I have as many elements as I like, here I show only one):

toolSeries = {
    "Series": "12345678A",
    "Serials" : ["123321", "123321", "54654", "357", "386758"],
}

and my binding is like so:

<tr *ngFor='let tools of toolSeries' height="50px">
    <td class="tableEntryText">{{tools.Series}}</td>
    <td class="tableEntryText">
        <select class="noBorder additionalSelectStyle" name="filter_for" (change)="OnSerialChanged($event.target)">
            <option *ngFor = 'let serial of tools.Serials'>
                {{serial}}
            </option>
        </select>
    </td>
<tr>

All good, works fine.

Now I need to add the following: each Tool Serial can have a "state". So I modify my data structure like so:

toolSeries = [
  {
    "Series": "12345678A",
    "Serials" : ["199921", "123321", "54654", "357", "386758"],
    "State": ["OK","BAD","BAD","UNKNOWN", "OK"]
  },

So, I add another column to my HTML table and now my code becomes:

<tr *ngFor='let tools of toolSeries' height="50px">
    <td class="tableEntryText">{{tools.Series}}</td>
    <td class="tableEntryText">
        <select class="noBorder additionalSelectStyle" name="filter_for" (change)="OnSerialChanged($event.target)">
            <option *ngFor = 'let serial of tools.Serials'>
                {{serial}}
            </option>
        </select>
    </td>
    <td class="tableEntryText">
        <label class="labelAdjust">{{series.State[0]}}</label>
    </td>
</tr>

Now as it stands, {{series.State[0]}} will mean that the the new field always shows the value of the first state for each serial.

Question: How should I write the binding so that the State of the field will reflect the state of the Serial selected in the drop down? So for example, when the user selects "123321" from the dropdown my new column's cell should show "BAD" instead of "OK".

Thanks for any help.

Upvotes: 1

Views: 4580

Answers (3)

user3738290
user3738290

Reputation: 445

Thank you both very much for taking the time to answer, I very much appreciate it. Your answers taught me a lot. In the end I did indeed change the data structure to one which enabled me to use less data-binding code.

Upvotes: 0

Amnah Razzaki
Amnah Razzaki

Reputation: 502

Stackblitz

My approach is quite similar to @DKidwell answer here, but instead of saving and looking up the value of selected tool.serial. I'm saving the index of selected tool.serial in ngModel & retrieving the tool.State value on same index if exists else there is no error and no value in tool.State. So, even if the length of these arrays mismatched your code will work, but still probably its a good idea to rethink your data structure if this is going to be get more complex.

<select class="noBorder additionalSelectStyle" name="filter_for" [(ngModel)]="selectedSerial">
  <option value="" disabled>Select a  serial</option>
  <option *ngFor = 'let serial of tools?.Serials; let i = index' [value]="i">
    {{serial}}
</option>
</select>
  </td>
  <td class="tableEntryText">
      <label class="labelAdjust">{{(tools?.State[selectedSerial]) ||  ''}} </label>
  </td>
</tr>

Upvotes: 1

David Kidwell
David Kidwell

Reputation: 720

There are some other considerations here but the quick and dirty way to do what you want is this,

<select [(ngModel)]="selectedValue" class="noBorder additionalSelectStyle" name="filter_for" (change)="OnSerialChanged($event.target)">
    <option *ngFor = 'let serial of tools.Serials' [ngValue]="serial">
        {{serial}}
    </option>
</select>

<td class="tableEntryText">
    <label class="labelAdjust">{{tools.State[tools.Serials.indexOf(selectedValue)]}}</label>
</td>

You have to bind a value to your select so that you know what the selected option is and then you need to find the index of that value in the tools.Serials array and use that index in tools.State to get the corresponding state. You will also need to declare the selectedValue variable in your .ts file,

public selectedValue: number;

Keep in mind this assumes that tools.Serials and tools.State have the same number of elements. If they ever become out of sync you will likely have errors.

The better solution is likely to rethink your data structure and associate the states with their serials in a more direct way.

Upvotes: 1

Related Questions