Ответ 1
обновление для версии 2.0.0
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, ModalComponent, CompComponent],
providers: [SharedService],
entryComponents: [CompComponent],
bootstrap: [ App, ModalComponent ]
})
export class AppModule{}
export class ModalComponent {
@ViewChild('theBody', {read: ViewContainerRef}) theBody;
cmp:ComponentRef;
constructor(
sharedService:SharedService,
private componentFactoryResolver: ComponentFactoryResolver,
injector: Injector) {
sharedService.showModal.subscribe(type => {
if(this.cmp) {
this.cmp.destroy();
}
let factory = this.componentFactoryResolver.resolveComponentFactory(type);
this.cmpRef = this.theBody.createComponent(factory)
$('#theModal').modal('show');
});
}
close() {
if(this.cmp) {
this.cmp.destroy();
}
this.cmp = null;
}
}
Совет
Если одно приложение изменяет состояние в SharedService
или вызывает метод, из-за которого Observable
испускает значение, а абонент находится в другом приложении, тогда эмиттер, код в подписчике выполняется в NgZone
излучателя.
Поэтому, подписываясь на наблюдаемый в SharedService
, используйте
class MyComponent {
constructor(private zone:NgZone, private sharedService:SharedService) {
private sharedService.subscribe(data => this.zone.run() => {
// event handler code here
});
}
}
Подробнее о том, как инициировать обнаружение изменений см. Запуск Angular2 вручную изменить обнаружение
оригинальный
Динамически добавленный HTML не обрабатывается Angular и не приводит к созданию или добавлению компонентов или директив.
Вы не можете добавлять компоненты вне корневого компонента углов (AppComponent), используя (устаревший) DynamicComponentLoader
ViewContainerRef.createComponent()
(Angular 2 динамических вкладки с помощью выбранных пользователем компонентов).
Я предполагаю, что лучший подход состоит в том, чтобы создать второй компонент вне корневого компонента Angulars, чтобы вызвать bootstrap()
для каждого и использовать совместно используемый сервис для связи:
var sharedService = new SharedService();
bootstrap(AppComponent, [provide(SharedService, {useValue: sharedService})]);
bootstrap(ModalComponent, [provide(SharedService, {useValue: sharedService})]);
Пример плеера beta.17
Пример плеера beta.14
@Injectable()
export class SharedService {
showModal:Subject = new Subject();
}
@Component({
selector: 'comp-comp',
template: `MyComponent`
})
export class CompComponent { }
@Component({
selector: 'modal-comp',
template: `
<div class="modal fade" id="theModal" tabindex="-1" role="dialog" aria-labelledby="theModalLabel">
<div class="modal-dialog largeWidth" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="theModalLabel">The Label</h4></div>
<div class="modal-body" #theBody>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" (close)="close()">Close</button>
</div></div></div></div>
`
})
export class ModalComponent {
cmp:ComponentRef;
constructor(sharedService:SharedService, dcl: DynamicComponentLoader, injector: Injector, elementRef: ElementRef) {
sharedService.showModal.subscribe(type => {
if(this.cmp) {
this.cmp.dispose();
}
dcl.loadIntoLocation(type, elementRef, 'theBody')
.then(cmp => {
this.cmp = cmp;
$('#theModal').modal('show');
});
});
}
close() {
if(this.cmp) {
this.cmp.dispose();
}
this.cmp = null;
}
}
@Component({
selector: 'my-app',
template: `
<h1>My First Attribute Directive</h1>
<button (click)="showDialog()">show modal</button>
<br>
<br>`,
})
export class AppComponent {
constructor(private sharedService:SharedService) {}
showDialog() {
this.sharedService.showModal.next(CompComponent);
}
}