angularmodal-dialogngx-bootstrap-modal

Ngx-boostrap modal send deleted entity id to another component


I have a list of posts and if I click on a post, an ngx-bootstrap modal opens, showing details of the post. Now I how 2 options. Either close the modal after reading the information or pressing a delete button to delete the post. The delete works well, but the post only disappears from the page after a refresh and I want it to disappear right away. I was thinking I could emit the id of the deleted post and then I could filter through the list of posts and simply eliminate the one whose id is no longer in the list. But this doesn't work, because the emitter doesn't seem to reach the so called parent component. This is what I've tried:

  <div class="modal-body">
    <form>
        <p>About</p>
        <div class="form-check">
            <p>{{post.about}}</p>
        </div>
    </form>
  </div>
  <div class="modal-footer">
    <button type="button"  class="btn" (click)="deletePost()">Delete</button>
    <button type="button" class="btn btn-default" (click)="bsModalRef.hide()">Cancel</button>
  </div>
  @Input() post: any;
  @Output() postDeleted: EventEmitter<any> = new EventEmitter(); 


 deleteBadge() {
    this.postService.deletePost(this.post.id)
    .subscribe({
      next: () => {
        this.bsModalRef.hide();
        this.triggerEvent(this.post.id);
      },
      error: err => console.log(err)
    })
  }

  
  triggerEvent(id: number) {
    this.postDeleted.emit(id);
  }

And this is the parent component, where I open the modal:

getPosts() {
    this.postService.getPosts().subscribe({
      next: (posts: any[]) => this.posts= posts,
      error: err => console.log(err)
    })
  }

openPostModal(post: any) {
    const setup = {
      class: 'modal-dialog-centered'
    };

    this.postModal = this.modalService.show(ViewPostModalComponent, setup);
    this.postModal.content.post = post;
  }

onPostDeleted(id: any) {
    this.posts = JSON.parse(
      JSON.stringify(this.posts.filter((post) => post.id !== id))
    );
  }

And in the HTML of the parent I have this:

 <div *ngFor="let post of posts">
           <div (postDeleted)="onPostDeleted($event)">
           <img src="{{post.photo.url}}" (click)="openPostModal(post)">
           <p>{{post.name}}</p>
 </div>

Solution

  • It doesn't work because postDeleted belongs to your modal component, not div. You should subscribe to postDeleted in openPostModal. And it's better to use Subject instead of EventEmitter here, because EventEmitter is designed for interaction between components.

    In your modal component:

    // without @Output() 
    postDeleted$: Subject<any> = new Subject();
    

    In parent component:

    openPostModal(post: any) {
        const setup = {
          class: 'modal-dialog-centered'
        };
    
        this.postModal = this.modalService.show(ViewPostModalComponent, setup);
        this.postModal.content.post = post;
        // take(1) is used to prevent memory leak
        this.postModal.content.postDeleted$.pipe(
          take(1)
        ).subscribe((id) => this.onPostDeleted(id));
    
      }