首页 文章

通过父组件以编程方式删除子组件

提问于
浏览
2

我想知道是否可以在Angular 2中执行以下操作 . 拥有一个包含此模板的组件(例如):

ParentComponent模板

<div>
  <childOne></childOne>

  <childTwo *ngFor="let item of items">
    whatever
  </childTwo>
</div>

有没有办法从ParentComponent使用ViewContainerRef删除这些项目,如下所示?

var viewContainerRef = /* get ParentComponent ViewContainerRef */
var index = viewContainerRef.indexOf(childViewRef);
viewContainerRef.remove(index);

我尝试使用类似于此处提出的解决方案来检索子ViewRef:Angular2 , How to find index of a view inside a viewContianer

但indexOf返回-1,就好像容器中没有子ViewRef一样 .

我想删除ParentComponent之外的这些子组件,而不是在ParentComponent代码中,比如从items数组中删除或通过绑定 .

我也尝试使用Renderer中的destroyView方法,但没有效果 . NgFor正在迭代items数组并为每个childTwo创建嵌入视图,如果在这种情况下,从ChildTwo注入器获得的ViewRef(如链接解决方案中所提出的)与这些EmbeddedViewRef相同,我不这样做 .

有没有办法做那样的事情?

谢谢 .

更新*** *

我会尝试简化一些我想要实现的目标 . 我正在开发一个仪表板,用户可以使用以下API创建其组件:

@Component({ selector: 'child' })
class UserChildComponent extends DashboardComponent {
  (...)
}

@Component({ selector: 'parent' })
class UserParentComponent extends DashboardComponent {

  @ViewChildren(UserChildComponent) m_children: QueryList<UserChildComponent>;

  private models: Array<ChildModel>;

  (...)
}

/* UserParentComponent template
<div>
  <child></child>
  <child *ngFor="let model of models"></child>
</div>

我有一个所有Dashboard组件的逻辑树及其相互之间的关系(父/子),因为子类型和其他东西在这里没有关注的场景 .

这是我想到的场景:用户可以删除任何这些子仪表板组件 . 我想,在需要所有关系树的情况下,将子项从父项中删除并通知用户(可能通过父项中的ViewChildren) . 或者我实际上可以在父级上调用方法,以便用户可以更新其模型数组,这可能是最好的方法 .

我只想到一种方式,用户可以减少工作量,而不必担心同步模型\组件(在这种情况下)

再次感谢 .

2 回答

  • 1

    您可以使用

    let element = querySelector(...);
    element.parentNode.removeChild(element)
    

    但是不鼓励在Angular2中使用直接DOM访问 . Angular2本身不提供您想要的API . 在Angular2中,您应该只更新模型并让Angular执行DOM操作 .

  • 1

    我能想到的一个可能的解决方案是创建一个具有如下事件 Launcher 的服务:

    export class ChildRemoveNotifierService{
    
         public $remove = new EventEmitter<string>();
    
    }
    

    然后,我们需要一个可以删除元素并创建它们的指令:

    @Directive({ selector: '[remover]' })
    export class RemoveDirective {
    
      @Input remove = '';
      constructor(
        private removerService:ChildRemoveNotifierService ,
        private _templateRef: TemplateRef,
        private _viewContainer: ViewContainerRef
        ) {
    
    
              let subscription =
              this.removerService.$remove.subscribe((tobeRemoved)=>{
                 if(tobeRemoved===this.remove){
                     this._viewContainer.clear();
                     subscription.unsubscribe();
                 }
              })
        }
    

    然后,你会像这样使用它:

    <span *remover='my-component'>
         <my-component></my-component>
     </span>
    

    基本上,任何需要动态删除的组件都应该用* remover指令包装 .

    然后,现在,everyOne可以删除所有人:)

    您的父组件可以触发这样的事件:

    export class ParentComponentOrAnyOther{
    
         constructor(private removerService:ChildRemoveNotifierService){
    
          }
    
          removeAComponent(){
    
              removerService.$remove.emit('my-component');
    
          }
    }
    

    这不是理想的,或者也许是,我不知道 .

    但我确实知道这绝对是Angular方式而你没有做任何DOM操作 .

    这样,你就拥有了所有的Angular2生命周期,特别是onDestroy事件将在my-component中被触发 .

    编辑:

    我认为这也会奏效:

    <my-component *remover='my-component'></my-component>
    

相关问题