how to delete a specific view from viewcontainer a

2020-05-02 02:03发布

问题:

In the following example, https://stackblitz.com/edit/angular-1acvol

I have creating multiple views using a TemplateRef and am attaching them to the same ViewContainer. But I am unable to figure out how to delete a specific View from the ViewContainer.

I know there are methods in ViewContainerRef like remove, detach and indexOf but I can't find a way to use them.

My template is

  <ng-template #thumbnailTemplate let-description="description">
    <div>
      <a href="#" (click)="deleteView()">Delete {{description}}} (</a>
    </div>
  </ng-template> 

The HTML is

<button #showTmplButton (click)="showTemplate()">{{buttonTitle}} </button>
<ng-container #vc></ng-container>

On clicking button, a new instance of the template gets added to ng-container. I want that on clicking a, that specific view gets deleted. But how do I know at which index of ViewContainer the view is stored and how to pass it to the deleteView function?

The logic to add a view is

  showTemplate(){  

    let view:ViewRef = this.vc.createEmbeddedView(this.tmpl, {description: 'description '+(this.id++)}) 

  }

But I don't how to delete a specific view

deleteView(){
    /*what to do here.  
    this.vc.remove(...);
    */

     }

回答1:

This seems to work. I am trying to delete a view from a container but I needed the reference of the view to delete.

Few new things I learned

When creating a view, we can pass a context object. This is like data passed to the template (see it as arguments and template is the function).

let view:ViewRef = this.vc.createEmbeddedView(this.tmpl, 
   {option:{divId:'thumbnail-'+(this.divId++),
    closeId:'close-'+(this.closeId++)
    }} );

If the template is

 <ng-template #thumbnailTemplate let-option="option"  let-index="index">
    <div id="{{option.divId}}"> 
      <img> 
      <a href="#" id="{{option.closeId}}" (click)="deleteIt(option)">template  inserted at index {{option.index}}, {{option.divId}}, {{option.closeId}}</a>

    </div>
  </ng-template> 

then let-option matches with option:, {option:{divId:'thumbnail-'+(this.divId++), closeId:'close-'+(this.closeId++)}} is the context object and I can then use option in the template as {{option.divId}}. It is explained here - What is $implicit in angular 2?

Once I learned how to pass data a template, I thought of using createEmbeddedView and passed index to it and then later also update the context object of the view with the index value. I can then later retrieve this value and use it in remove of ngContainerRef to remove that view. That seemed to work initially but after I stored say views 0,1,2,3 and then deleted index 1, the container would reorganise the views and assign them new indexes. However, the value in the context object didnt get updated.

Thus, instead of storing index, I store ViewRef in the context object and when I want to delete a view, I called indexOf to get the correct index value and use it in remove

Code.

  showTemplate(){  

   /*
   You need to pass an object with the keys that match the let-keyname syntax:
   The ng-template in html uses let-option and let-index so the object passed need to have index and option keys
   */

   //create view and pass context data
    let view:ViewRef = this.vc.createEmbeddedView(this.tmpl, 
   {option:{divId:'thumbnail-'+(this.divId++),
    closeId:'close-'+(this.closeId++)
    }} );

//after view is created, get its index and updat context. Note that ViewIndexRef was not in initial context object.
    view.context.option.viewIndexRef = view;//store ref of this view

  }

//pass the entier context object to the function
  deleteIt(option){
//get viewRef from context and then get index of the viewref
    let index = this.vc.indexOf(option.viewIndexRef)
//remove the view
    this.vc.remove(index);

     }

In the html, template gets option object and the click callback of a passes it to deleteIt function

<ng-template #thumbnailTemplate let-option="option"  let-index="index">
    <div id="{{option.divId}}"> 
      <img> 
      <a href="#" id="{{option.closeId}}" (click)="deleteIt(option)">template  inserted at index {{option.index}}, {{option.divId}}, {{option.closeId}}</a>

    </div>
  </ng-template>


标签: angular