I came up with a solution that met my needs at that time. I am using angular-cli with WebPack and it worked for my needs. I do not understand all the examples that I saw that say to use "templateUrl: / Template / Index", where the path is the path to the MVC view. It just doesn't work, because the path cannot be found inside any of the associated views created by WebPack. Perhaps these people do not use angular-cli and WebPack.
This stackoverflow answer - How can I use / create a dynamic template to compile a dynamic component with Angular 2.0? , helped a lot in creating the next directive. This directive will output a partial view of mvc and compile it. It allows you to execute Razor / server logic, as well as compiling some Angular. Although, in fact, including other components inside this part of MVC, it was problematic. If you earn, let me know what you did. In my case, I just needed to render the server to place it exactly where I wanted it in the Angular 2 spa.
MvcPartialDirective
import { Component, Directive, NgModule, Input, ViewContainerRef, Compiler, ComponentFactory, ModuleWithComponentFactories, ComponentRef, ReflectiveInjector, OnInit, OnDestroy } from '@angular/core'; import { RouterModule } from '@angular/router'; import { CommonModule } from '@angular/common'; import {Http} from "@angular/http"; import 'rxjs/add/operator/map'; export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> { const cmpClass = class DynamicComponent {}; const decoratedCmp = Component(metadata)(cmpClass); @NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp] }) class DynamicHtmlModule { } return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule) .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => { return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp); }); } @Directive({ selector: 'mvc-partial' }) export class MvcPartialDirective implements OnInit, OnDestroy { html: string = '<p></p>'; @Input() url: string; cmpRef: ComponentRef<any>; constructor(private vcRef: ViewContainerRef, private compiler: Compiler, private http: Http) { } ngOnInit() { this.http.get(this.url) .map(res => res.text()) .subscribe( (html) => { this.html = html; if (!html) return; if(this.cmpRef) { this.cmpRef.destroy(); } const compMetadata = new Component({ selector: 'dynamic-html', template: this.html, }); createComponentFactory(this.compiler, compMetadata) .then(factory => { const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector); this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []); }); }, err => console.log(err), () => console.log('MvcPartial complete') ); } ngOnDestroy() { if(this.cmpRef) { this.cmpRef.destroy(); } } }
in some-component.html (if your mvc application shares the domain with your spa)
<mvc-partial [url]="'/stuffs/mvcstuff'"></mvc-partial>
Mvcstuff.cshtml
@{ ViewBag.Title = "This is some MVC stuff!!!"; } <div> <h2>MVC Stuff:</h2> <h4>@ViewBag.Title</h4> <h2>Angular Stuff:</h2> <h4>{{1 + 1}}</h4> </div>
in stuffscontroller.cs
public PartialViewResult MvcStuff() => PartialView();