2

I created a chips component, which has a remove button. After I click on this button, I want to remove the whole component from the DOM including it's wrapper HTML tag.

chips.component.ts

@Component({
    selector: "app-chips",
    template: `<div class="close-btn" #myChips>My chips
                   <i class="fa fa-times" aria-hidden="true" (click)="remove(myChips)"></i>
               </div>`
})
export class ChipsComponent {
    public remove(self: HTMLElement): void {
        self.remove();
    }
}

app.component.html

<app-chips></app-chips>
<app-chips></app-chips>
<app-chips></app-chips>

On the page it renders like this:

<app-chips>
    <div class="close-btn" #myChips>My chips
        <i class="fa fa-times" aria-hidden="true" (click)="remove(myChips)"></i>
    </div>
</app-chips>

After I click to remove button, it removes only the chips, but the <app-chips></app-chips> stays in DOM.

How can I remove the whole component?

Objective

I try to create chips component like this: enter image description here

Raphaël Balet
  • 6,334
  • 6
  • 41
  • 78
Runtime Terror
  • 6,242
  • 11
  • 50
  • 90

2 Answers2

0

Old topic, but since I struggle trying the same...

Sadly, a component cannot auto delete himself

So we have the following options.

1: ViewContainerRef

You could generate your component with a componentFactoryResolver, store them into an array, and then use this array to completely remove those components

<ng-template #chipsContainer></ng-template>
@ViewChild('chipsContainer', { read: ViewContainerRef, static: true })
chipsContainer: ViewContainerRef

loadedChips: any[] = []

addChip(attributes: any) {
  let componentFactory = this.componentFactoryResolver.resolveComponentFactory(
    AppChipsComponent,
  )
  let componentRef = this.componentLoaderContainer.createComponent(componentFactory)
  let ref: any = componentRef.instance
  ref.init(this.loadedChips.lenght) // Will be used to know which index should be removed

  this.loadedChips.push(componentRef)

  // Subscribing to the EventEmitter from the chip
  ref.emitDeletion
    .subscribe((index: number) => {
       this._removeChip(index)
    })
}

private _removeChip(index: number) {
  this.loadedChips[index].destroy()
  this.loadedChips.splice(index, 1)
}

Then, what you should additionally add to your chip component

export class AppChipsComponent {
  private _index: number

  @Output() emitDeletion = new EventEmitter<boolean>()

  init(index: number) {
    this._index = index
  }

  remove() {
    this.emitDeletion.emit(this._index)
  }
}

2: Javascript

If the first example seems to complex (And it is, if you want my opinion '^^) you could simply add an id to the html or anything else that helps you recognize it

then, when clicking on remove() your can get it, and remove it properly.

<!-- You can use an *ngFor to make it simpler -->
<app-chips id="appChips-0" [id]="appChips-0"></app-chips>
<app-chips id="appChips-1" [id]="appChips-1"></app-chips>
<app-chips id="appChips-2" [id]="appChips-2"></app-chips>
export class AppChipsComponent {
  @Input() id!: string

  remove() {
    document.getElementById(this.id).remove()
  }
}

Voilà.

Raphaël Balet
  • 6,334
  • 6
  • 41
  • 78
-1

Set your component selector as your html ID like so:

@Component({
    selector: "#myChips", // like this
    template: `<div class="ibl-close-btn" #myChips>My chips
                   <i class="fa fa-times" aria-hidden="true" (click)="remove(myChips)"></i>
               </div>`
})
Sunny Gohil
  • 319
  • 1
  • 11