是否可以在多个位置显示一个角度分量的单个实例?

时间:2019-07-05 09:59:46

标签: angular

假设我有这样的html:

      <div *ngIf="(isVisible | async)">
        <app-mycomponent></app-mycomponent>
      </div>
      <div *ngIf="!(isVisible | async)">
        <app-mycomponent></app-mycomponent>
      </div>

带有可切换isVisible的按钮。每当我切换可见性时,都会创建一个新的组件实例。

所以我的问题是:切换可见性时,我可以更改实现以使用相同的AppMyComponent实例。例如。通过具有可动态添加app-mycomponent的包装器组件或其他方式。

编辑:我的实际情况非常复杂,即使这个示例没有意义,我对此也很感兴趣。

EDIT2:这是stackbliz,可以解决我的问题。

2 个答案:

答案 0 :(得分:4)

此答案基于此stackblitz example中提供的answer,与我提出的类似问题相同。

第1步:创建一个指令,该指令将在您希望拥有可重用组件的任何地方使用。

@Directive({
  selector: '[reusable-outlet]',
})
export class ReusableDirective implements OnInit {

  constructor(
    private viewContainerRef: ViewContainerRef,
    private reusableService: ReusableService
  ) { }

  public ngOnInit(): void {
    this.reusableService.attach(this.viewContainerRef);
  }

}

步骤2 创建将负责以下服务的服务:

  • 动态创建将被重用的组件
  • 将该组件附加和分离到在步骤〜1中创建的指令的视图容器中。

注意:知道何时分离组件是基于路由器事件的,但是,如果您需要更改组件的位置而不进行导航更改,则应该可以基于消息来代替它。

@Injectable()
export class ReusableService {

  private componentRef: ComponentRef<ReusableComponent>;

  private currentViewContainerRef: ViewContainerRef;

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private injector: Injector,
    private router: Router
  ) {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(ReusableComponent);
    this.componentRef = componentFactory.create(injector);

    this.router.events.subscribe(event => {
      if (event instanceof NavigationStart && this.currentViewContainerRef) {
        this.detach(this.currentViewContainerRef);
      }
    });
  }

  public attach(viewContainerRef: ViewContainerRef) {
    this.currentViewContainerRef = viewContainerRef;
    viewContainerRef.insert(this.componentRef.hostView);
  }

  public detach(viewContainerRef: ViewContainerRef) {
    viewContainerRef.detach(viewContainerRef.indexOf(this.componentRef.hostView));
  }

}

答案 1 :(得分:0)

1)在#dynamicComponentContainer中插入视图。

2)我们可以跟踪变量或对象中的组件或所有组件并销毁它们:-

3)或者,在存储DOM中的新组件时,通过存储最后一个引用并在插入新组件之前.destroy()来销毁上一个组件。

.html

 <ng-container #dynamicComponentContainer id="dynamicComponentContainer"></ng-container>

.ts

public loadComponent(cmptName){
     switch (cmptName) {
         case 'abcComponent':
             cmptName = abcComponent;
             break;
         case 'cdeComponent':
             cmptName = cdeComponent;
             break;
        }

    let componentRef = this.componentFactoryResolver.resolveComponentFactory(cmptName).create(this.injector);

     // check for duplicates and update with new one
      //   this.checkForDuplicateCmp(componentRef);

     //   send data to respecting component using `inputdata`       
     componentRef.instance['inputdata'] = initCmpInputdata;

     let indexView = this.dynamicComponentContainer.length;
                            this.dynamicComponentContainer.insert(componentRef.hostView, indexView);

    // keep reference of lastComponent added to DOM
     this.lastComponent = componentRef;

    }      



public remove component(){
    // destroy components as on click
        this.lastComponent.destroy();

      //or
       //for (var j = 1; j < this.dynamicComponentContainer.length; j++) {
      //  this.dynamicComponentContainer.remove(j);  //or pass j 
      //       }
      //    }

abcComponent.ts

@Input() inputdata: any;

注意:-对于abccomoponent调用的多个实例

loadComponent(abccomoponent )