I have a custom structural directive in my angular app like this:
@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;
}
}
}
Using it in the html template :
<ng-container *appIfData="(referenceService.documentUserTypes$ | async) as userDocTypes">
But I can't access the declared variable 'userDocTypes' in the rest of the template like i was doing when using ngIf for example.
I guess it's a normal behavior but I can't find a good way to do this.
Any help would be greatly appreciated.
EDIT :
this is how i am using it, it is in a child element. As said before it works fine if I just change it to *ngIf :

EDIT 2 :
Updated directive
@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;
}
}
the variable which declared in as is only accessible within its child element like
<ng-container *appIfData="(referenceService.documentUserTypes$ | async) as userDocTypes">
<div>{{ userDocTypes }}</div> // you can access here
</ng-container>
<div>{{ userDocTypes }}</div> // you cannot access here
I think you got confused with template reference which can be accessed with in its template
<div>
<input type="text" #myInput value="123">
</div>
<div>{{ myInput.value }}</div> // you can access template variable outside of it
After looking a t Andrei comment in his answer, I was using this :
/**
* 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$;
}
and changed it to this:
/**
* 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();
}
not the best but the workaround works
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With