Search code examples
angularprimengangular9angular10

Access sub array in html angular


I am working on angular app. I am using primeng carousel in my app. My code is as follows:

<p-carousel
  [value]="products"
  [numVisible]="3"
  [numScroll]="3"
  [circular]="false"
  [responsiveOptions]="responsiveOptions"
>
  <ng-template pTemplate="header">
    <h5>Basic</h5>
  </ng-template>
  <ng-template let-product let-i="index" pTemplate="item">
    <div class="product-item">
      <div class="product-item-content">
        <div class="p-mb-3"></div>
        <div>
          <p>{{ product.id }}</p>
          <h4 class="p-mb-1">{{ product.name }}</h4>
          <h6 class="p-mt-0 p-mb-3">${{ product.price }}</h6>
          <span
            [class]="
              'product-badge status-' + product.inventoryStatus.toLowerCase()
            "
            >{{ product.inventoryStatus }}</span
          >
          <div class="car-buttons p-mt-5">
            <p-button
              type="button"
              styleClass="p-button p-button-rounded p-mr-2"
              icon="pi pi-search"
            ></p-button>
            <p-button
              type="button"
              styleClass="p-button-success p-button-rounded p-mr-2"
              icon="pi pi-star"
            ></p-button>
            <p-button
              type="button"
              styleClass="p-button-help p-button-rounded"
              icon="pi pi-cog"
            ></p-button>
          </div>
        </div>
      </div>

      <div
        *ngFor="let cityData of myData; let i = index"
        style="position: relative;margin-top: 2rem;border-bottom: 1px solid #4E5668;"
      >
        <div style="display: flex; margin:1em; ">
          <span style="flex:1;">{{ cityData.name }}</span>
          <span style="flex:1;">
            <p-checkbox
              name="product"
              [value]="cityData.id"
              (onChange)="toggleVisibility($event, cityData, product)"
              #checkbox
            ></p-checkbox>
          </span>
        </div>
      </div>
    </div>
  </ng-template>
</p-carousel>

Stackblitz:

https://stackblitz.com/edit/primeng-carousel-demo-fjw4ap?file=src%2Fapp%2Fapp.component.ts

In this carousel I have some checkboxes as shown in stackblitz. My array is as follows -

myData = [
    {
      myid: 1,
      name: 'paris',
      status: [
        {
          id: 1000,
          active: 1,
        },
        {
          id: 1001,
          active: 1,
        },
      ],
    },
    {
      myid: 2,
      name: 'London',
      status: [
        {
          id: 1003,
          active: 1,
        },
        {
          id: 1004,
          active: 1,
        },
      ],
    },
  ]; 

So I want to set checkbox as checked when id from product array matches id in status array of myData array. So, in html at runtime I want to write a code when myData is looping, I need to access status array of myData and match id. if product.id and myData.status[i].id are equal, then I need to check active field. If active is 1 then set checkbox as true, if active is 0 then se checkbox as false.

How can I have this code in html to access status array in above html code , pass id and access value of active variable?


Solution

  • Try to avoid complex operations in HTML templates. They are not performant & a bad practice.

    Also, calling a method (that could return true/false if product id is in status array) from HTML is also not recommended.

    The best way to do it is to transform status array into an Object of type [productId: string]:number

    {
          myid: 1,
          name: 'paris',
          status: {
              "1000":1,
              "1001":1,   
           }
    },
    

    This makes it easier to access a product Id myData.status.id.

    Approach 1: If you have control over the Backend, you should transform the status into an object from there.

    Approach 2: You can't control Backend: Transform the status array into an object when you get it in the response. Use Rxjs pipe & map the response:

     getData().pipe(map(response=>{
      //Assuming response is the data currently in this.myData
      response.forEach(city=>{
        const mappedStatus=city.status.reduce((acc,current)=>{
          acc[current.id]=current.active;
          return acc;
        },{});
    
        city.status={...mappedStatus};
      });
      return response;
    }))
    

    In HTML where you place your checkbox: (A simple checkbox. Add other handlers that you require)

     <p-checkbox
        binary="true"
        trueValue="1"
        falseValue="0"
        [ngModel]="cityData.status[product.id]"
      ></p-checkbox>