An Angular2 @Component combines the equivalents of MVC Controller and View. This mostly also applies to MVC PartialViews.
In my application, TypeScript dynamically adds PartialViews to the page’s HTML.
Migrating the code to Angular2, the page’s component, let’s call it ParentComponent, contains an array of ChildComponents. If a new ChildComponent is added to the array, Angular2 will automatically render its template or templateURL, and add the resulting HTML inside the <childcomponent> tag
<childcomponent *ngFor="#c of childcomponents" [childdata]="c"> </childcomponent>
Your custom JavaScript code can then process the rendered component in one of the LifeCycle Hooks.
The story gets more complicated if your code needs to dynamically select which PartialView to render. Of course, there is the NgSwitch directive, which acts as the templating’s switch/case mechanism, but template code may easily get ugly and overly complex.
The alternative is to define the template or templateURL programmatically by calling loader.loadIntoLocation() of DynamicComponentLoader, but, as GitHub issues show (#7815, #6701, #7596, #2753), this is not as straight-forward as one might hope, especially if template data-binding is involved (#6223, #7453, SO, SO).
The solution that I extracted from the referenced issues looks like this
constructor(private loader: DynamicComponentLoader, private elementRef: ElementRef, private ref: ChangeDetectorRef) { this.myData = ..some data..; this.myOtherData = ..some data..; } ngOnInit() { var templateURL = .... calculate template ...; this.loader.loadIntoLocation( this.toComponent(templateURL + '.html', null), this.elementRef, 'newItem' ).then(component => { component.instance.myData = this.myData; component.instance.myOtherData = this.myOtherData; this.ref.markForCheck() }); }
toComponent(templateUrl, directives = []) { @Component({ selector: 'child-fake-component', templateUrl: templateUrl, directives: [COMMON_DIRECTIVES]) class ChildFakeComponent {} return ChildFakeComponent; }
Note that I need ChangeDetectorRef to explicitly update the template because I deactivated change detection using ChangeDetectionStrategy.OnPush, so this need not apply to your case.
The essential part is that you need to copy all data referenced by the template to component.instance. #newItem is the anchor of the HTML element in the @Component’s template or template, and the loaded template will be attached after the original template, not replacing the original template.
Pingback: Migrating a TypeScript application from ASP.Net MVC to Angular2 – Lessons Learned | devioblog