Search code examples
javascripthtmlangulardevextremedevextreme-angular

Remove item from input button and from list?


Here is my all problem -> https://stackblitz.com/edit/dropdown-fill-empty-uecsjw?file=src%2Fapp%2Fapp.component.ts

Current occurrence.

When I select a few items from the drop-down menu and delete them on the button called 'Remove' on the deleted one from the listener in the input button it looks as if it is still selected and checked ( from input ).

I know the reason. Because when I click on the button and call the function I do not trigger on selection and there is no removedItems.

Question is it possible to delete the selected item on the button ( function removeTemplate ) and delete it in my input?

I am using devExreme component which inside have method removedItems but i need to remove and on click on button.

Code is here:

   trainingSelected(e) {
    this.newItems = this.selectedPlans.filter(
      p => !e.removedItems.includes(p)
    );
    this.newItems.push(...e.addedItems);
    console.log('new items, ' , this.newItems);
    this.selectedPlans = this.newItems;
  }

    removeTemplate(e, training){
    console.log(e)
    console.log(training)
    e.stopPropagation();
    this.existingIndex = this.selectedPlans.indexOf(training);
    this.selectedPlans.splice(this.existingIndex , 1);
    // this.newItems.filter(item => item.id !== training.id) 
  }

Solution

  • Of course we can delete the displayed value. To do this we need to take the reference for dx-tag-box component. I present two ways.

    Solution 1: Template reference

    • <dx-tag-box #tagBox add the template reference to dx-tag-box html tag
    • send tagBox as param of removeTemplate function <small (click)="removeTemplate($event, training, tagBox);" >

    On html

    <dx-tag-box #tagBox [items]="trainingPlan" displayExpr="name" valueExpr="id" [showSelectionControls]="true" required
        searchEnabled="true" noDataText="Ne postoji trening templato" placeholder="Izaberite trening templato"
        showClearButton="true" deferRendering="false" (onSelectionChanged)="trainingSelected($event)"
        selectAllMode="allPages" applyValueMode="useButtons">
    </dx-tag-box>
    
    
    <div *ngFor="let training of selectedPlans">
        <div class="py-3">
            <p> {{ training.id }} <small (click)="removeTemplate($event, training, tagBox);" > Remove </small> </p>
        </div>
    </div>
    

    On ts

    removeTemplate(e, training, tagBoxRef) {  // <-- reference
        this.existingIndex = this.selectedPlans.indexOf(training);
        this.selectedPlans.splice(this.existingIndex, 1);
    
        // Remove the value by index from tagBox reference.
        const displayedValue = tagBoxRef.value;
        const planIndexToRemove = displayedValue.findIndex(id => id === training.id);
        displayedValue.splice(planIndexToRemove, 1);
        tagBoxRef.value = displayedValue;
      }
    

    Working example: https://stackblitz.com/edit/dropdown-fill-empty-hczvpu

    Solution 2: ViewChild

    Using ViewChild get the component reference without change the params of removeTemplate function

    On html

    • <dx-tag-box #tagBox add the template reference to dx-tag-box html tag

    On ts

    • Create a reference for tagBox using ViewChild @ViewChild("tagBox") tagBoxRef; add this on top of AppComponent

    • Use this.tagBoxRef to reference to tagBox component

    removeTemplate(e, training) {
        this.existingIndex = this.selectedPlans.indexOf(training);
        this.selectedPlans.splice(this.existingIndex, 1);
    
        // Remove the value by index from tagBox reference.
        const displayedValue = this.tagBoxRef.value;
        const planIndexToRemove = displayedValue.findIndex(id => id === training.id);
        displayedValue.splice(planIndexToRemove, 1);
        this.tagBoxRef.value = displayedValue;
      }
    

    Working example: https://stackblitz.com/edit/dropdown-fill-empty-s2ztmy?file=src%2Fapp%2Fapp.component.ts