在结构指令中声明变量
Declare variable in structural directive
我的 angular 应用程序中有一个自定义结构指令,如下所示:
@Directive({
selector: '[appIfData]'
})
export class IfDataDirective {
private hasView = false;
@Input()
set appIfData(condition: boolean) {
if (condition && !this.hasView) {
this.viewContainerRef.clear();
this.viewContainerRef.createEmbeddedView(this.templateRef);
this.hasView = true;
} else if (!condition) {
this.viewContainerRef.clear();
const factory = this.componentFactoryResolver.resolveComponentFactory(ContentMessageComponent);
const messageComponentRef = this.viewContainerRef.createComponent(factory);
messageComponentRef.instance.message = 'No data is available yet';
messageComponentRef.instance.icon = 'fas fa-info';
this.hasView = false;
}
}
}
在 html 模板中使用它:
<ng-container *appIfData="(referenceService.documentUserTypes$ | async) as userDocTypes">
但是我无法访问模板其余部分中声明的变量 'userDocTypes',就像我在使用 ngIf
时所做的那样。
我想这是正常现象,但我找不到好的方法。
如有任何帮助,我们将不胜感激。
编辑:
这就是我使用它的方式,它在子元素中。
如前所述,如果我将其更改为 *ngIf,它就可以正常工作:
编辑 2:
更新指令
@Directive({
selector: '[appIfData]'
})
export class IfDataDirective {
private hasView = false;
@Input()
set appIfData(data: any) {
if (data && !this.hasView) {
this.viewContainerRef.clear();
this.viewContainerRef.createEmbeddedView(this.templateRef, { appIfData: data });
this.hasView = true;
} else if (!data) {
this.viewContainerRef.clear();
const factory = this.componentFactoryResolver.resolveComponentFactory(ContentMessageComponent);
const messageComponentRef = this.viewContainerRef.createComponent(factory);
messageComponentRef.instance.message = 'No data is available yet';
messageComponentRef.instance.icon = 'fas fa-info';
this.hasView = false;
}
}
在 as
中声明的变量只能在其子元素中访问,如
<ng-container *appIfData="(referenceService.documentUserTypes$ | async) as userDocTypes">
<div>{{ userDocTypes }}</div> // you can access here
</ng-container>
<div>{{ userDocTypes }}</div> // you cannot access here
我认为您对 template reference
感到困惑,可以在其模板中访问
<div>
<input type="text" #myInput value="123">
</div>
<div>{{ myInput.value }}</div> // you can access template variable outside of it
您可以像这样向 createEmbeddedView
添加上下文
this.viewContainerRef.createEmbeddedView(this.templateRef, {appIfData: condition});
另请注意,condition
在您的示例中不是布尔值,它可能会在 aot 编译期间崩溃。将条件类型更改为其他内容
看了 Andrei 在他的回答中的评论后,我使用了这个:
/**
* Cache for document user types
*/
public documentUserTypesCache$: BehaviorSubject<DocumentUserType[]>;
/**
* Get document user types
*/
public get documentUserTypes$(): BehaviorSubject<DocumentUserType[]> {
if (!this.documentUserTypesCache$) {
this.documentUserTypesCache$ = new BehaviorSubject<DocumentUserType[]>([]);
this.getDocumentUserTypes().pipe(tap(r => this.documentUserTypesCache$.next(r))).subscribe();
}
return this.documentUserTypesCache$;
}
并将其更改为:
/**
* Cache for document user types
*/
public documentUserTypesCache$: BehaviorSubject<DocumentUserType[]>;
/**
* Get document user types
*/
public get documentUserTypes(): DocumentUserType[] {
if (!this.documentUserTypesCache$) {
this.documentUserTypesCache$ = new BehaviorSubject<DocumentUserType[]>(null);
this.getDocumentUserTypes().pipe(
filter(r => r && r != null),
tap(r => this.documentUserTypesCache$.next(r))).subscribe();
}
return this.documentUserTypesCache$.getValue();
}
不是最好的,但解决方法有效
我的 angular 应用程序中有一个自定义结构指令,如下所示:
@Directive({
selector: '[appIfData]'
})
export class IfDataDirective {
private hasView = false;
@Input()
set appIfData(condition: boolean) {
if (condition && !this.hasView) {
this.viewContainerRef.clear();
this.viewContainerRef.createEmbeddedView(this.templateRef);
this.hasView = true;
} else if (!condition) {
this.viewContainerRef.clear();
const factory = this.componentFactoryResolver.resolveComponentFactory(ContentMessageComponent);
const messageComponentRef = this.viewContainerRef.createComponent(factory);
messageComponentRef.instance.message = 'No data is available yet';
messageComponentRef.instance.icon = 'fas fa-info';
this.hasView = false;
}
}
}
在 html 模板中使用它:
<ng-container *appIfData="(referenceService.documentUserTypes$ | async) as userDocTypes">
但是我无法访问模板其余部分中声明的变量 'userDocTypes',就像我在使用 ngIf
时所做的那样。
我想这是正常现象,但我找不到好的方法。
如有任何帮助,我们将不胜感激。
编辑:
这就是我使用它的方式,它在子元素中。 如前所述,如果我将其更改为 *ngIf,它就可以正常工作:
编辑 2:
更新指令
@Directive({
selector: '[appIfData]'
})
export class IfDataDirective {
private hasView = false;
@Input()
set appIfData(data: any) {
if (data && !this.hasView) {
this.viewContainerRef.clear();
this.viewContainerRef.createEmbeddedView(this.templateRef, { appIfData: data });
this.hasView = true;
} else if (!data) {
this.viewContainerRef.clear();
const factory = this.componentFactoryResolver.resolveComponentFactory(ContentMessageComponent);
const messageComponentRef = this.viewContainerRef.createComponent(factory);
messageComponentRef.instance.message = 'No data is available yet';
messageComponentRef.instance.icon = 'fas fa-info';
this.hasView = false;
}
}
在 as
中声明的变量只能在其子元素中访问,如
<ng-container *appIfData="(referenceService.documentUserTypes$ | async) as userDocTypes">
<div>{{ userDocTypes }}</div> // you can access here
</ng-container>
<div>{{ userDocTypes }}</div> // you cannot access here
我认为您对 template reference
感到困惑,可以在其模板中访问
<div>
<input type="text" #myInput value="123">
</div>
<div>{{ myInput.value }}</div> // you can access template variable outside of it
您可以像这样向 createEmbeddedView
添加上下文
this.viewContainerRef.createEmbeddedView(this.templateRef, {appIfData: condition});
另请注意,condition
在您的示例中不是布尔值,它可能会在 aot 编译期间崩溃。将条件类型更改为其他内容
看了 Andrei 在他的回答中的评论后,我使用了这个:
/**
* Cache for document user types
*/
public documentUserTypesCache$: BehaviorSubject<DocumentUserType[]>;
/**
* Get document user types
*/
public get documentUserTypes$(): BehaviorSubject<DocumentUserType[]> {
if (!this.documentUserTypesCache$) {
this.documentUserTypesCache$ = new BehaviorSubject<DocumentUserType[]>([]);
this.getDocumentUserTypes().pipe(tap(r => this.documentUserTypesCache$.next(r))).subscribe();
}
return this.documentUserTypesCache$;
}
并将其更改为:
/**
* Cache for document user types
*/
public documentUserTypesCache$: BehaviorSubject<DocumentUserType[]>;
/**
* Get document user types
*/
public get documentUserTypes(): DocumentUserType[] {
if (!this.documentUserTypesCache$) {
this.documentUserTypesCache$ = new BehaviorSubject<DocumentUserType[]>(null);
this.getDocumentUserTypes().pipe(
filter(r => r && r != null),
tap(r => this.documentUserTypesCache$.next(r))).subscribe();
}
return this.documentUserTypesCache$.getValue();
}
不是最好的,但解决方法有效