Wymyśliłem rozwiązanie, które zaspokoiło moje potrzeby w tym czasie. Używam angular-cli z WebPack, a to działało na moje potrzeby. Nie rozumiem wszystkich przykładów, które widziałem, aby używać "templateUrl: '/ Template/Index" ", gdzie ścieżka jest ścieżką do widoku MVC. To po prostu nie działa, ponieważ nie można znaleźć ścieżki w żadnym z dołączonych widoków tworzonych przez WebPack. Może ci ludzie nie używają angular-cli i WebPack.
Ta odpowiedź stackoverflow - How can I use/create dynamic template to compile dynamic Component with Angular 2.0? była bardzo pomocna przy tworzeniu poniższej dyrektywy. Ta dyrektywa pobierze wynik częściowego widoku mvc i skompiluje go. Pozwala to na uzyskanie logiki Razor/serwer, a także trochę kompilacji kątowej. Chociaż w rzeczywistości włączenie innych elementów w tym częściowym MVC było problematyczne. Jeśli to zadziała, daj mi znać, co zrobiłeś. W moim przypadku potrzebowałem renderowania serwera i umieszczenia go dokładnie tam, gdzie chciałem, w moim 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();
}
}
}
w pewne-component.html (zakładając swoje udziały MVC aplikacji domenę ze swoim 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>
w StuffsController.cs
public PartialViewResult MvcStuff() => PartialView();
To jest właściwa odpowiedź. Działa jak marzenie. Wydaje mi się, że czasami warto wstępnie renderować szablony kątowe na serwerze, aby można było łatwo renderować Nazwę użytkownika lub wykonywać inną logikę biznesową specyficzną dla tego użytkownika (uprawnienia itp.). –
To jedyny sposób, aby to osiągnąć? – k11k2
Pobranie ''undefined' nie daje się wpisać" ComponentFactory "' error –
k11k2