如何使用动态模板创建组件? (组件内联模板包含在内) [英] How to create a Component with a dynamic template? (Component transclude with inline template)
问题描述
我正在尝试创建一个组件,该组件内部具有动态模板字符串,该字符串可以访问模板上的局部变量.我尝试过的每种方法都以动态模板字符串"结尾而不是$compile
(用1角表示,请问好).
I'm trying to create a component that has a dynamic template string inside of it that can access the local variables on the template. Every approach I've tried ends up with the "dynamic template string" not being $compile
'd (angular 1 terminology, please excuse me).
这是下面组件的代码.在您看到评论的地方,我想在ngFor
中插入一个可以引用item
的模板字符串.
Here is the code for the component below. Where you see the comment I would like to insert a template string that can reference item
in the ngFor
.
@Component({
selector: 'ion-alpha-scroll',
template: `
<ion-scroll [ngStyle]="calculateScrollHeight()" scrollX="false" scrollY="true">
<ion-list class="ion-alpha-list-outer">
<div *ngFor="let items of sortedItems | mapToIterable;">
<ion-item-divider id="scroll-letter-{{items.key}}">{{items.key}}</ion-item-divider>
<ion-item *ngFor="let item of items.value">
<!-- how can I pass a dynamic template here that can reference item ? -->
</ion-item>
</div>
</ion-list>
</ion-scroll>
<ul class="ion-alpha-sidebar" [ngStyle]="calculateDimensionsForSidebar()">
<li (click)="alphaScrollGoToList(letter)" *ngFor="let letter of alphabet">
<div class="letter">{{letter}}</div>
</li>
</ul>
`,
pipes: [MapToIterable]
})
export class IonAlphaScroll {
@Input() listData: any;
@Input() key: string;
@Input() template: string;
....
}
理想情况下,我想让ion-alpha-scroll
的已包含内容在ngFor
中引用item
.我尝试在组件的必要ngFor
中使用ng-content
,但没有运气-
Ideally I would like to have the transcluded content of the ion-alpha-scroll
reference the item
in the ngFor
. I tried using ng-content
in the necessary ngFor
of the component and had no luck -
<ion-alpha-scroll *ngIf="breeds" [listData]="breeds" key="$t">
{{item.$t}}
</ion-alpha-scroll>
我尝试过的一件事就是这样-
One thing I tried was like this -
<ion-alpha-scroll *ngIf="breeds" [listData]="breeds" key="$t" [template]="alphaScrollTemplate">
</ion-alpha-scroll>
alphaScrollTemplate
只是包含{{item.$t}}
的字符串.然后,我尝试在评论提出问题的组件中引用它,但是它不起作用-
The alphaScrollTemplate
is just a string containing {{item.$t}}
. I then tried to reference it in the component where the comment is asking the question but it doesn't work -
...
<ion-item *ngFor="let item of items.value">
{{template}}
<!-- this just outputs {{item.$t}} literally -->
</ion-item>
...
我真的很好奇,甚至在角度2的情况下是否也有可能.我刚刚发现这个问题与我的非常相似.谢谢您的任何帮助或建议.
I'm really curious if this is even possible with angular 2 yet. I just found this question which is very similar to mine. Any help or suggestions will be greatly appreciated, thanks.
推荐答案
这是我用于angular 2.0.0-rc.3的解决方案
Here is the solution I used for angular 2.0.0-rc.3
此解决方案创建一个动态组件,并使用ViewContainerRef
和ComponentFactory
加载它. 这是GitHub上的ionic 2组件.
This solution creates a dynamic component and loads it by using ViewContainerRef
and ComponentFactory
. Here is the ionic 2 component on GitHub.
export function createComponentFactory(resolver: ComponentResolver, metadata: ComponentMetadata): Promise<ComponentFactory<any>> {
const cmpClass = class DynamicComponent {};
const decoratedCmp = Component(metadata)(cmpClass);
return resolver.resolveComponent(decoratedCmp);
}
@Directive({
selector: 'dynamic-html-outlet',
})
export class DynamicHTMLOutlet {
@Input() src: string;
@Input() ionAlphaScrollRef: any;
@Input() currentPageClass: any;
constructor(private vcRef: ViewContainerRef, private resolver: ComponentResolver) {
}
ngOnChanges() {
if (!this.src) return;
const metadata = new ComponentMetadata({
selector: 'dynamic-html',
template: this.src,
pipes: [MapToIterable]
});
createComponentFactory(this.resolver, metadata).then(factory => {
const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
let component = this.vcRef.createComponent(factory, 0, injector, []);
component.instance.ionAlphaScrollRef = this.ionAlphaScrollRef;
component.instance.currentPageClass = this.currentPageClass;
});
}
}
@Component({
selector: 'ion-alpha-scroll',
template: `
<dynamic-html-outlet
[src]="alphaScrollTemplate"
[ionAlphaScrollRef]="ionAlphaScrollRef"
[currentPageClass]="currentPageClass">
</dynamic-html-outlet>
`,
pipes: [MapToIterable],
directives: [DynamicHTMLOutlet]
})
export class IonAlphaScroll {
@Input() listData: any;
@Input() key: string;
@Input() itemTemplate: string;
@Input() currentPageClass: any;
@Input() triggerChange: any;
private _scrollEle: HTMLElement;
sortedItems: any = {};
alphabet: any = [];
alphaScrollTemplate: string;
ionAlphaScrollRef = this;
constructor(
@Host() private _content: Content,
private _elementRef: ElementRef,
private vcRef: ViewContainerRef,
private resolver: ComponentResolver
) {
}
ngOnInit() {
this.alphaScrollTemplate = `
<style>
.ion-alpha-sidebar {
position: fixed;
right: 0;
display: flex;
flex-flow: column;
z-index: 50000;
}
.ion-alpha-sidebar li {
flex: 1 1 auto;
list-style: none;
width: 15px;
text-align: center;
}
</style>
<ion-scroll class="ion-alpha-scroll" [ngStyle]="ionAlphaScrollRef.calculateScrollDimensions()" scrollX="false" scrollY="true">
<ion-list class="ion-alpha-list-outer">
<div *ngFor="let items of ionAlphaScrollRef.sortedItems | mapToIterable; trackBy:ionAlphaScrollRef.trackBySortedItems">
<ion-item-divider id="scroll-letter-{{items.key}}">{{items.key}}</ion-item-divider>
<ion-item *ngFor="let item of items.value">
${this.itemTemplate}
</ion-item>
</div>
</ion-list>
</ion-scroll>
<ul class="ion-alpha-sidebar" [ngStyle]="ionAlphaScrollRef.calculateDimensionsForSidebar()">
<li *ngFor="let letter of ionAlphaScrollRef.alphabet" tappable (click)="ionAlphaScrollRef.alphaScrollGoToList(letter)">
<a>{{letter}}</a>
</li>
</ul>
`;
setTimeout(() => {
this._scrollEle = this._elementRef.nativeElement.querySelector('scroll-content');
this.setupHammerHandlers();
});
}
ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
let tmp = {};
for (let i = 0; i < this.listData.length; i++) {
let letter = this.listData[i][this.key].toUpperCase().charAt(0);
if (typeof tmp[letter] === 'undefined') {
tmp[letter] = [];
}
tmp[letter].push(this.listData[i]);
}
this.alphabet = this.iterateAlphabet(tmp);
this.sortedItems = tmp;
}
// ....
}
这篇关于如何使用动态模板创建组件? (组件内联模板包含在内)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!