Event triggered on all elements generated by ngFor in angular 7

不打扰是莪最后的温柔 提交于 2021-02-10 16:30:00

问题


I have an Order screen where I have a list of items to buy. In front of every item, I have a plus and minus button and an input field where I can specify the quantity of the item I need to buy. I am using *ngFor to iterate through an array and display the items. Even I am creating plus button, minus button and an input text field for that item using this *ngFor. I am using 2-way data binding to get and set the data into the input field.

But, the issue is, when I click the increment button, all the items are getting incremented instead of that particular item for which I clicked the plus button. Same issue with minus button as well.

This issue is because there is an only property which is getting bind to all the iterations of *ngFor.

    <div class="row mt-2 mb-2" *ngFor="let item of listItems; let i = index">
            <div class="col-sm-6">   
                <img src= "{{ item.imgUrl }}" alt="Item Img">
                <span> {{ item.name.split(' ').slice(0,2).join(' ').replace(":", "").replace(",", "") }}</span>             
            </div>
            <div class="col-sm-6 m-auto">
              <button id="minus-image" class="minus mr-2" (click)="onMinusClick()"><img src="../../assets/icon/minus.png" alt="minus Img"></button>
              <input type="text" id="buyNumInput" class="buyNum" [(ngModel)]="buyNumInput">
              <button id="plus-image" class="plus ml-2" (click)="onPlusClick()"><img src="../../assets/icon/plus.png" alt="plus Img"></button>
              <span class="price ml-3 text-right"> {{ item.price }} gold</span> 
            </div>
    </div>

in .ts file:

    buyNumInput = 0;
    onPlusClick(){
    this.buyNumInput++;
    }

    onMinusClick(){
      this.buyNumInput--;
    }

Expected result: When + or - button of that item is clicked then the input value of that item should be changed. All other items input values shouldn't be changed.


回答1:


Yes, that is because you are binding the same value buyNumInput to all the items.

One way is to maintain separate array to store the values for each item. And when you click the button, pass the index of an item in the list. So that you increment/decrement it accordingly.

buyNumInput = [];

ngOnInit() {
   for(let i=0; i<this.listItems.length; i++){
        this.buyNumInput.push(0);
   }
}

onPlusClick(i){
   this.buyNumInput[i]++;
}

onMinusClick(i){
   this.buyNumInput[i]--;
}

html code

<div class="row mt-2 mb-2" *ngFor="let item of listItems; let i = index">
    <div class="col-sm-6">
        <img src= "{{ item.imgUrl }}" alt="Item Img">
            <span> {{ item.name.split(' ').slice(0,2).join(' ').replace(":", "").replace(",", "") }}</span>             
  </div>
  <div class="col-sm-6 m-auto">
    <button id="minus-image" class="minus mr-2" (click)="onMinusClick(i)"><img src="../../assets/icon/minus.png" alt="minus Img"></button>
    <input type="text" id="buyNumInput" class="buyNum" [(ngModel)]="buyNumInput[i]">
    <button id="plus-image" class="plus ml-2" (click)="onPlusClick(i)"><img src="../../assets/icon/plus.png" alt="plus Img"></button>
    <span class="price ml-3 text-right"> {{ item.price }} gold</span> 
</div>

Example




回答2:


It seems you have just one number property in your component so it's shared between the items. One of the solutions could be: https://stackblitz.com/edit/angular-bbkun4
I recommend doing all the heavy string formatting inside .ts file(method 'getDisplayName') instead of directly inside the template.

typescript part:

getDisplayName(item) {
    return item.name;
}

onPlusClick(item) {
    item.count++;
}

onMinusClick(item) {
    item.count = item.count === 0 ? 0 : item.count - 1;
}

onInputChanged(item, amount) {
    item.count = amount;
}

and html:

<div *ngFor="let item of listItems; let i = index">
    <div>
        <img src="{{ item.imgUrl }}" alt="Item Img" />
        <span> {{ getDisplayName(item) }}</span>
    </div>
    <div>
        <button id="minus-image" (click)="onMinusClick(item)">
            <img src="../../assets/icon/minus.png" alt="minus Img" />
        </button>
        <input
            type="number"
            id="buyNumInput"
            [ngModel]="item.count"
            (ngModelChange)="onInputChanged(item, $event)"
        />
        <button id="plus-image" (click)="onPlusClick(item)">
            <img src="../../assets/icon/plus.png" alt="plus Img" />
        </button>
        {{ item.price }} gold
    </div>
</div>


来源:https://stackoverflow.com/questions/56199957/event-triggered-on-all-elements-generated-by-ngfor-in-angular-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!