Search code examples
angularformsdrop-down-menueditshopping-cart

Dynamic edit form for each item in a shopping cart


I want the user to be able to edit the quantity of an item in the shopping cart without opening a new page or dialog. The quantity displayed in the cart should turn into a drop-down menu, and the user should be able to select which one they prefer. They should also have the option to choose a custom amount if the number they want isn't on the dropdown.

The problem is that I don't know how many items will be in the cart at any given time, and the user can edit multiple items at once, but there is only one edit form so changes to one ends up affecting the other items being edited as well.

My html code looks like this:

<form class="in-cart" *ngFor="let item of items" [formGroup]="editForm">
...
    <div class="cart__quantity">
        <div *ngIf="item.Edit == false">
            {{item.Quantity}}
        </div>
        <mat-form-field *ngIf="item.Edit == true">
             <select matNativeControl [formControl]="editForm.controls.itemQuantity">
                <option *ngFor="let quantity of item.Quant" [ngValue]="quantity">
                    {{quantity}}
                </option>
            </select>
        </mat-form-field>
        <!-- custom quantity -->
        <mat-form-field  *ngIf="editForm.controls.itemQuantity.value == 0">
            <input matInput [formControl]="editForm.controls.itemQuantityCustom"/>
        </mat-form-field>
    </div>
    ...
    <div class="cart__actions">
        <a (click)="editInCart(item)" *ngIf="item.Edit == false">Edit</a>
        <a (click)="cancelEdit(item)" *ngIf="item.Edit == true">Cancel Edit</a>
        <a (click)="saveEdit(item)" *ngIf="item.Edit == true">Save Edit</a>
        <a (click)="removeFromCart(item)">Remove</a>
    </div>
</form>

The custom quantity input field appears under every item in the cart if even one of the dropdowns chooses the 'other' option. I am trying to make it show up only for the specific item that is being edited.


Solution

  • If you want to edit at time several items, you need or a FormArray or an array of FormGroups

    With an array of FormGroups

    //You declared the array
    editForm:FormGroup[]=[];
    

    Your .html

    <!--see that use formControlName not formControl-->
    <form class="in-cart" *ngFor="let item of items;let i=index" [formGroup]="editForm[i]">
       ....
       <mat-form-field *ngIf="item.Edit == true">
          a!--better use formControlName
          <select matNativeControl formControlName="itemQuantity">
               ...
          </select>
       <mat-form-field>
         <!--use editForm[i] to access the value-->
       <mat-form-field  *ngIf="editForm[i].controls.itemQuantity.value == 0">
           <input matInput formControlName="itemQuantityCustom"/>
       </mat-form-field>
       <!--pass the "index" to your function
       <a (click)="editInCart(item,i)" *ngIf="item.Edit == false">Edit</a>
       ...
    </div>
    

    And the function editInCart

    editInCart(item:any,index:number)
    {
       this.editForm[index]=new FormGroup({
           itemQuantity:new FormControl(item.itemQuantity),
           itemQuantityCustom:new FormControl(item.itemQuantity),
       })
    }