Reputation: 3810
I am trying to create a generic directive which will take a class type for rule validation and according to the rule in the class the directive will either show or hide an element.
This is my attempt so far.
PLUNKER Demo
myIf-Directive.ts
@Directive({
selector: '[myIf]'
})
export class MyIfDirective {
constructor(private _viewContainer: ViewContainerRef,
private _template: TemplateRef<Object>)
{ }
@Input() set myIf(rule: string) {
//rule class type will come as string
//how can I use string token to get dependency from injector?
//currently harcoded
//will the injector create new instance or pass on instance from parent?
let injector = ReflectiveInjector.resolveAndCreate([AdminOnly]);
let adminOnly : IRule = injector.get(AdminOnly);
let show = adminOnly.shouldShowElement();
show ? this.showItem() : this.hideItem();
}
private showItem() {
this._viewContainer.createEmbeddedView(this._template);
}
private hideItem() {
this._viewContainer.clear();
}
}
app-component.ts
@Component({
selector: 'my-app',
template: `
<div *myIf="'AdminOnly'">
<h2>Hello {{name}}</h2>
</div>
`,
})
export class App {
name:string;
constructor() {
this.name = 'Angular2'
}
}
But I am stuck in 2 places:
No Provider for AuthService
Any suggestion whether this is the right way to do it or where I am going wrong is highly appreciated.
Upvotes: 2
Views: 5053
Reputation: 899
Just update for Angular version 10+:
@Injectable({
providedIn: 'any'
})
export class AdminOnly { ... }
import { Injector } from '@angular/core';
...
const injector: Injector = Injector.create({
providers: [{provide: AdminOnly, deps: []}]
});
const adminOnly: AdminOnly = injector.get(AdminOnly);
let show = adminOnly.shouldShowElement();
...
Upvotes: 0
Reputation: 657731
You need to pass the parent injector like
export class MyIfDirective {
constructor(private injector:Injector, private _viewContainer: ViewContainerRef,
private _template: TemplateRef<Object>)
{ }
@Input() set myIf(rule: string) {
let resolvedProviders = ReflectiveInjector.resolve([AdminOnly]);
let childInjector = ReflectiveInjector.fromResolvedProviders(resolvedProviders, this.injector);
let adminOnly : IRule = childInjector.get(AdminOnly);
let show = adminOnly.shouldShowElement();
show ? this.showItem() : this.hideItem();
}
private showItem() {
this._viewContainer.createEmbeddedView(this._template);
}
private hideItem() {
this._viewContainer.clear();
}
}
See also Inject service with ReflectiveInjector without specifying all classes in the dependency tree
Upvotes: 4