我有一个小问题!
我有一个自定义指令,根据输入入口放置隐藏属性。
import { Directive, ElementRef, Input, OnInit, Renderer2 } from '@angular/core';
@Directive({
selector: '[ticketingPrimeCreateTicketButtonActive]'
})
export class CreateTicketButtonActiveDirective implements OnInit {
@Input() ticketingPrimeCreateTicketButtonActive: string;
constructor(private elRef: ElementRef, private renderer: Renderer2) {}
ngOnInit() {
console.log(this.ticketingPrimeCreateTicketButtonActive);
if (!(this.ticketingPrimeCreateTicketButtonActive === 'Administrador' || this.ticketingPrimeCreateTicketButtonActive === 'Comercial')) {
this.renderer.setAttribute(this.elRef.nativeElement, 'hidden', 'true');
}
}
}
这个指令之所以有效,是因为当我硬编码入口时,它像这样工作:
<button [ticketingPrimeCreateTicketButtonActive]="'Administrador'" class="col-1 add" [ngClass]="{ addInSmall: isSmallOrXSmall() }" (click)="addTicket()">
<span class="material-icons add-icon"> add_to_photos </span>
</button>
那么问题是我必须从数据库中获取字符串
我尝试创建一个可观察对象并使用管道异步,但它总是取null。组件的显著代码:
export class TicketingKanbanComponent implements OnInit, OnDestroy, AfterViewInit {
public activeUserRoleNameSubject: BehaviorSubject<string>;
public activeUserRoleName$: Observable<string>;
....
}
async ngOnInit(): Promise<void> {
const roleUid = (await
this.userBaseGesRoleRepository.findOneByActiveUser().toPromise()).metadata.roleUid;
this.role = (await this.roleRespository.findOne(roleUid).toPromise()).metadata.name;
this.activeUserRoleNameSubject = new BehaviorSubject<string>(this.role)
this.activeUserRoleName$ = this.getActiveUserRoleName$();
....
}
private async getActiveUserRoleName() {
console.log(this.role);
this.activeUserRoleNameSubject.next(this.role);
}
private getActiveUserRoleName$(): Observable<string> {
return this.activeUserRoleNameSubject.asObservable();
}
当我这样传递参数时:
<button [ticketingPrimeCreateTicketButtonActive]="(this.activeUserRoleName$ | async )" class="col-1 add" [ngClass]="{ addInSmall: isSmallOrXSmall() }" (click)="addTicket()">
<span class="material-icons add-icon"> add_to_photos </span>
</button>
指令总是接收null!
我知道这是生命周期的一部分,但我已经尝试了所有我认为应该有效的方法,它对我说NO NO NO
编辑:
使用各种控制台。在ngoninit从DDBB获取值之前,它抛出了这个指令。
但是我以前不知道怎么做。
EDIT 2:
我终于使它工作了,使DDBB在指令内部进行磋商。
,但我仍然不如果它应该是可能的解决咨询数据库在组件加载模板之前,因为在构造函数中我不能使用async等待。
据我所知,你的问题显然是组件和指令构建的生命周期。指令被创建并从它的输入ticketingPrimeCreateTicketButtonActive
中获取值,因为它是一个数据库获取,很可能是空的。它将继续监听这个值,但不会执行你想要的行为,并在ngOnInit中定义,因为这个生命周期事件只发生一次。
我能想到至少两种可能的方法来解决这个问题。
首先
你可以放弃使用自定义指令而依赖于[hidden]="logicHere"
。通过使用Renderer来操作HTML并不是一种非常常见的做法。它看起来像这样:
<button [hidden]="!((this.activeUserRoleName$ | async ) === 'Administrator' || (this.activeUserRoleName$ | async ) === 'Comercial')" class="col-1 add" [ngClass]="{ addInSmall: isSmallOrXSmall() }" (click)="addTicket()">
<span class="material-icons add-icon"> add_to_photos </span>
</button>
或者直接用自定义函数替换隐藏的逻辑。
第二
你可以继续使用你的自定义指令逻辑,但是你需要改变@Input
的管理方式。Angular有一个很好的页面来解释这个:https://angular.io/guide/component-interaction
结果是这样的:
import { Directive, ElementRef, Input, OnInit, Renderer2 } from '@angular/core';
@Directive({
selector: '[ticketingPrimeCreateTicketButtonActive]'
})
export class CreateTicketButtonActiveDirective implements OnInit {
@Input()
get ticketingPrimeCreateTicketButtonActive() {
return this._ticketingPrimeCreateTicketButtonActive;
};
set ticketingPrimeCreateTicketButtonActive(ticketingPrimeCreateTicketButtonActive: string){
this._ticketingPrimeCreateTicketButtonActive = ticketingPrimeCreateTicketButtonActive;
this.customFunction();
}
private _ticketingPrimeCreateTicketButtonActive = '';
constructor(private elRef: ElementRef, private renderer: Renderer2) {}
customFunction() {
if (!(this._ticketingPrimeCreateTicketButtonActive === 'Administrador' || this._ticketingPrimeCreateTicketButtonActive === 'Comercial')) {
this.renderer.setAttribute(this.elRef.nativeElement, 'hidden', 'true');
} else {
this.renderer.setAttribute(this.elRef.nativeElement, 'hidden', 'false');
}
}
}
这里每次@Input
的值发生变化时都调用customFunction
。
另一种解决方案是使用解析器来延迟组件。当它到达ngOnInit时,值已经从数据库中获取了。看看Angular的解析器