Equivalent of $compile in Angular 2

后端 未结 9 993
名媛妹妹
名媛妹妹 2020-11-21 06:50

I want to manually compile some HTML containing directives. What is the equivalent of $compile in Angular 2?

For example, in Angular 1, I could dynamic

9条回答
  •  温柔的废话
    2020-11-21 07:19

    I know this issue is old, but I spent weeks trying to figure out how to make this work with AOT enabled. I was able to compile an object but never able to execute existing components. Well I finally decided to change tact, as I was't looking to compile code so much as execute a custom template. My thought was to add the html which anyone can do and loop though the existing factories. In doing so I can search for the element/attribute/etc. names and execute the component on that HTMLElement. I was able to get it working and figured I should share this to save someone else the immense amount of time I wasted on it.

    @Component({
        selector: "compile",
        template: "",
        inputs: ["html"]
    })
    export class CompileHtmlComponent implements OnDestroy {
        constructor(
            private content: ViewContainerRef,
            private injector: Injector,
            private ngModRef: NgModuleRef
        ) { }
    
        ngOnDestroy() {
            this.DestroyComponents();
        }
    
        private _ComponentRefCollection: any[] = null;
        private _Html: string;
    
        get Html(): string {
            return this._Html;
        }
        @Input("html") set Html(val: string) {
            // recompile when the html value is set
            this._Html = (val || "") + "";
            this.TemplateHTMLCompile(this._Html);
        }
    
        private DestroyComponents() { // we need to remove the components we compiled
            if (this._ComponentRefCollection) {
                this._ComponentRefCollection.forEach((c) => {
                    c.destroy();
                });
            }
            this._ComponentRefCollection = new Array();
        }
    
        private TemplateHTMLCompile(html) {
            this.DestroyComponents();
            this.content.element.nativeElement.innerHTML = html;
            var ref = this.content.element.nativeElement;
            var factories = (this.ngModRef.componentFactoryResolver as any)._factories;
            // here we loop though the factories, find the element based on the selector
            factories.forEach((comp: ComponentFactory) => {
                var list = ref.querySelectorAll(comp.selector);
                list.forEach((item) => {
                    var parent = item.parentNode;
                    var next = item.nextSibling;
                    var ngContentNodes: any[][] = new Array(); // this is for the viewchild/viewchildren of this object
    
                    comp.ngContentSelectors.forEach((sel) => {
                        var ngContentList: any[] = new Array();
    
                        if (sel == "*") // all children;
                        {
                            item.childNodes.forEach((c) => {
                                ngContentList.push(c);
                            });
                        }
                        else {
                            var selList = item.querySelectorAll(sel);
    
                            selList.forEach((l) => {
                                ngContentList.push(l);
                            });
                        }
    
                        ngContentNodes.push(ngContentList);
                    });
                    // here is where we compile the factory based on the node we have
                    let component = comp.create(this.injector, ngContentNodes, item, this.ngModRef);
    
                    this._ComponentRefCollection.push(component); // save for our destroy call
                    // we need to move the newly compiled element, as it was appended to this components html
                    if (next) parent.insertBefore(component.location.nativeElement, next);
                    else parent.appendChild(component.location.nativeElement);
    
                    component.hostView.detectChanges(); // tell the component to detectchanges
                });
            });
        }
    }
    

提交回复
热议问题