Angular:破坏动态组件

时间:2018-04-05 09:57:03

标签: angular factory

使用聊天应用程序,我使用它来创建多个ChatComponent(作为动态组件)。

loader.service.ts

import { ChatComponent } from '../components/shared/chat/chat.component';

@Injectable()
export class LoaderService {

    constructor( @Inject(ComponentFactoryResolver) factoryResolver ) 
    { 
      this.factoryResolver = factoryResolver
    }

    setRootViewContainerRef(viewContainerRef){
      this.rootViewContainer = viewContainerRef
    }

    addDynamicComponent(timeIdentifier){
      const factory = this.factoryResolver.resolveComponentFactory(ChatComponent);      
      const component = factory.create(this.rootViewContainer.parentInjector)
      component.instance.timeIdentifier = timeIdentifier;
      this.rootViewContainer.insert(component.hostView)
    }
  }

chat-container.component.ts

export class ChatContainerComponent implements OnInit {

    @ViewChild('chat', { read: ViewContainerRef }) viewContainerRef: ViewContainerRef

    constructor( protected loaderService: LoaderService, protected route: ActivatedRoute ) { }

    ngOnInit() {

        this.route.params.subscribe(params => {
            this.loaderService.setRootViewContainerRef(this.viewContainerRef)
            this.loaderService.addDynamicComponent(params['timeIdentifier'])
        });
    }
}

这样我可以生成多个" ChatComponent"作为动态组件。

但是一旦创建它们怎么能摧毁它们呢?

修改

我在ChatComponent中添加了这个(由组件工厂创建)

this.cmpRef.destroy();

但是当我这样称呼时,我陷入了无限循环,出现了错误:

ERROR RangeError: Maximum call stack size exceeded

2 个答案:

答案 0 :(得分:0)

工厂创建的组件属于public class Structure { public Parameter[] InputParams { get; set; } public Parameter OutputParam { get; set; } public Graph Expression { get; set; } } public class Parameter { public string Name { get; set; } public string Type { get; set; } } public class Builder { public static Expression Build(Structure s) { var inputParams = new ParameterExpression[s.InputParams.Length]; int index = 0; foreach (var param in s.InputParams) { inputParams[index++] = Expression.Parameter(GetDataType(param.Type), param.Name); } Type lambdaDefinition = GetLambdaTypeDefinition(s.InputParams.Length); Type[] typeArgs = s.InputParams.Select(p => GetDataType(p.Type)).Concat(new Type[] { GetDataType(s.OutputParam.Type) }).ToArray(); Type lambdaType = lambdaDefinition.MakeGenericType(typeArgs); ParameterExpression delegVar = Expression.Variable(lambdaType, "sum"); LambdaExpression expression = Expression.Lambda( Expression.Block( new[] { delegVar }, Expression.Assign(delegVar, Expression.Lambda( Expression.Block( // some work is done here Expression.Invoke(delegVar, inputParams) ), inputParams ) ), Expression.Invoke(delegVar, inputParams) ), inputParams ); return expression; } private static Type GetDataType(string type) { switch (type) { case DataTypes.Boolean: return typeof(bool); case DataTypes.Number: return typeof(double); case DataTypes.NumArray: return typeof(double[]); } return null; } private static Type GetLambdaTypeDefinition(int inputLength) { switch (inputLength) { case 1: return typeof(Func<,>); case 2: return typeof(Func<,,>); case 3: return typeof(Func<,,,>); case 4: return typeof(Func<,,,,>); case 5: return typeof(Func<,,,,,>); case 6: return typeof(Func<,,,,,,>); case 7: return typeof(Func<,,,,,,,>); case 8: return typeof(Func<,,,,,,,,>); case 9: return typeof(Func<,,,,,,,,,>); case 10: return typeof(Func<,,,,,,,,,,>); case 11: return typeof(Func<,,,,,,,,,,,>); case 12: return typeof(Func<,,,,,,,,,,,,>); case 13: return typeof(Func<,,,,,,,,,,,,,>); case 14: return typeof(Func<,,,,,,,,,,,,,,>); case 15: return typeof(Func<,,,,,,,,,,,,,,,>); case 16: return typeof(Func<,,,,,,,,,,,,,,,,>); default: throw new Exception("Too many input parameters"); } } } 类型。 该类具有ComponentRef函数来销毁实例和相关结构。

在此处查看:https://angular.io/api/core/ComponentRef

答案 1 :(得分:0)

我找到了销毁组件的更好方法,您可以这样做:

addDynamicComponent(timeIdentifier){
  const factory = this.factoryResolver.resolveComponentFactory(ChatComponent);      
  const component = factory.create(this.rootViewContainer.parentInjector)
  component.instance.timeIdentifier = timeIdentifier;
  component.instance.autodestroy = () => component.destroy();
  this.rootViewContainer.insert(component.hostView)
}

在组件类内部,创建方法autodestroy,并在需要销毁它时调用它。