我正在尝试设置一个标签系统,允许组件自己注册(带标题).第一个选项卡就像一个收件箱,有大量的操作/链接项可供用户选择,每个点击都应该能够在点击时实例化一个新组件.动作/链接来自JSON.
然后,实例化的组件将自己注册为新选项卡.
我不确定这是否是"最佳"方法?Sofar我见过的唯一指南是静态标签,这没有帮助.
到目前为止,我只有主要引导的标签服务在整个应用程序中持续存在,看起来像这样的东西.
export interface ITab { title: string; }
@Injectable()
export class TabsService {
private tabs = new Set<ITab>();
addTab(title: string): ITab {
let tab: ITab = { title };
this.tabs.add(tab);
return tab;
}
removeTab(tab: ITab) {
this.tabs.delete(tab);
}
}
Run Code Online (Sandbox Code Playgroud)
问题:
DynamicComponentBuilder会被使用吗?ng-content,但我找不到有关如何使用它的更多信息编辑:尝试澄清
将收件箱视为邮件收件箱,将项目作为JSON提取并显示多个项目.单击其中一个项目后,将创建一个新选项卡,其中包含该项操作"类型".然后类型是一个组件
Edit2:图片
我想创建动态组件并将这些组件的视图插入到容器中.
我认为这可以通过ViewContainerRef来实现.
但我不知道,我们能得到ViewContainerRef任何组件吗?如果是的话怎么样?我是Angular的新手,如果有任何其他好的解决方案可以处理这种情况,请建议我.
更新 我认为,我非常接近解决方案.下面是代码.
app.component.ts
import {Component} from '@angular/core';
import {ContainerComponet} from './container.component'
@Component({
selector: 'my-app',
template: `
<container> </container>
`,
directives: [ContainerComponet]
})
export class AppComponent {
constructor() { }
}
Run Code Online (Sandbox Code Playgroud)
container.component.ts
import {Component, ComponentResolver, ViewContainerRef} from '@angular/core'
import {controlBoxComponent as controlBox} from './controlBox.component';
@Component({
selector: 'container',
template: 'container'
})
export class ContainerComponet {
constructor(viewContainer: ViewContainerRef, private _cr: ComponentResolver) {
this._cr.resolveComponent(controlBox)
.then(cmpFactory => {
const ctxInjector = viewContainer.injector;
return viewContainer.createComponent(cmpFactory, 0, ctxInjector);
})
} …Run Code Online (Sandbox Code Playgroud) 有没有办法在Angular 2中动态插入一个组件作为DOM标记的子(而不是兄弟)?
有很多例子可以将动态组件作为给定ViewContainerRef标签的兄弟插入,例如(从RC3开始):
@Component({
selector: '...',
template: '<div #placeholder></div>'
})
export class SomeComponent {
@ViewChild('placeholder', {read: ViewContainerRef}) placeholder;
constructor(private componentResolver: ComponentResolver) {}
ngAfterViewInit() {
this.componentResolver.resolveComponent(MyDynamicComponent).then((factory) => {
this.componentRef = this.placeholder.createComponent(factory);
});
}
}
Run Code Online (Sandbox Code Playgroud)
但这会生成类似于以下内容的DOM:
<div></div>
<my-dynamic-component></my-dynamic-component>
Run Code Online (Sandbox Code Playgroud)
预期结果:
<div>
<my-dynamic-component></my-dynamic-component>
</div>
Run Code Online (Sandbox Code Playgroud)
使用SomeComponent's ViewContainerRef具有相同的结果,它仍然将生成的组件插入为兄弟,而不是孩子.我可以使用一个解决方案,其中模板为空,动态组件插入模板中(在组件选择器标签内).
当使用像ng2-dragula这样的库从动态组件列表中拖动并从模型更新中受益时,DOM结构非常重要.额外的div位于可拖动元素的列表中,但在模型之外,打破了拖放逻辑.
有人说这是不可能的(参见此评论),但这听起来像是一个非常令人惊讶的限制.
我正在寻找将已知/已定义组件注入应用程序根目录并将@Input()选项投影到该组件上的最佳方法.
这对于在应用程序主体中创建模态/工具提示等内容是必要的,这样overflow:hidden/ etc不会扭曲位置或完全切断它.
我发现我可以得到它ApplicationRef然后hackily向上遍历并找到ViewContainerRef.
constructor(private applicationRef: ApplicationRef) {
}
getRootViewContainerRef(): ViewContainerRef {
return this.applicationRef['_rootComponents'][0]['_hostElement'].vcRef;
}
Run Code Online (Sandbox Code Playgroud)
一旦我有了,我就可以调用createComponent如下:
appendNextToLocation<T>(componentClass: Type<T>, location: ViewContainerRef): ComponentRef<T> {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentClass);
const parentInjector = location.parentInjector;
return location.createComponent(componentFactory, location.length, parentInjector);
}
Run Code Online (Sandbox Code Playgroud)
但现在我已经创建了组件,但我的所有Input属性都没有完成.为了实现这一点,我必须手动遍历我的选项并在appendNextToLocation实例的结果上设置如下:
const props = Object.getOwnPropertyNames(options);
for(const prop of props) {
component.instance[prop] = options[prop];
}
Run Code Online (Sandbox Code Playgroud)
现在我意识到你可以做一些DI来注入选项,但这使得它在尝试用作普通组件时不可重复使用.这是什么看起来像参考:
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(ComponentClass);
let parentInjector = location.parentInjector;
let providers = ReflectiveInjector.resolve([
{ …Run Code Online (Sandbox Code Playgroud) 我使用谷歌地图javascript api,我必须在InfoWindow中显示一个Angular组件.
在我的项目中,我使用该Jsonp服务加载谷歌地图API .比我有google.maps.Map可用的对象.稍后在组件中我创建了一些标记并将一个点击监听器附加到它们:
TypeScript:
let marker = new google.maps.Marker(opts);
marker.setValues({placeId: item[0]});
marker.addListener('click', (ev: google.maps.MouseEvent) => this.onMarkerClick(marker, ev));
Run Code Online (Sandbox Code Playgroud)
然后在click处理程序中我想打开一个包含Angular组件的信息窗口:
TypeScript:
private onMarkerClick(marker: google.maps.Marker, ev: google.maps.MouseEvent) {
var div = document.createElement();
this.placeInfoWindow.setContent(div);
// Magic should happen here somehow
// this.placeInfoWindow.setContent('<app-info-view-element></app-info-view-element>');
this.placeInfoWindow.open(this.map, marker);
}
Run Code Online (Sandbox Code Playgroud)
我最终做的是一些香草JS:
TypeScript:
private onMarkerClick(marker: google.maps.Marker, ev: google.maps.MouseEvent) {
let div = document.createElement('div');
div.className = 'map-info-window-container';
div.style.height = '140px';
div.style.width = '240px';
this.placeInfoWindow.setContent(div);
this.placeInfoWindow.open(this.map, marker);
this.placesService.getPlace(marker.get('id')).subscribe(res => {
this.decorateInfoWindow(div, res.name, …Run Code Online (Sandbox Code Playgroud) 我有一个(我认为是一个相当常见的)问题,我找不到使用当前Angular 4.x架构解决的好方法.也许有一种方法我还没有找到,但我已经进行了广泛的搜索.
我想将一些动态的,用户生成的HTML内容插入到Angular应用程序中.这个HTML内容我还包括一些已知的(包含在模块声明中)应该呈现的角度组件.下面是一些puesdo-app HTML可能会帮助我解释:
<app-component>
<!-- standard angular header and router-outlet -->
<app-header>
<app-nav>
<ul>
<li routerLink="/page-one">First Page</li>
<li routerLink="/page-two">Second Page</li>
<li routerLink="/page-three">Third Page</li>
</ul>
</app-nav>
</app-header>
<router-outlet></router-outlet>
<!--
the dynamic content would be inserted into the <main> element as HTML with angular <app-... tags
the content in the HTML content inserted main tag could contain anything
the angular components within the content should be initalized as normal
-->
<main>
<h1>Title</h1>
<app-component>
<p>this component and its content should be initalized …Run Code Online (Sandbox Code Playgroud) 我在 angular 4 中插入这样的动态页面内容:
<app-component>
<main [innerHTML]="dynamicHTML"></main>
</app-component>
Run Code Online (Sandbox Code Playgroud)
这将呈现为:
<app-component>
<main>
<div>
<div id="insertionPoint">
</div>
</div>
</main>
</app-component>
Run Code Online (Sandbox Code Playgroud)
是否有可能得到ViewContainerRef的div#insertionPoint已动态添加。在div#insertionPoint可能是被装载到一个大的HTML文档的任何地方<main>。
我想使用ViewContainerRef.createComponent()和ComponentFactoryResolver来在动态 HTML 中插入一个 Angular 组件。