Build single directive to perform both Structural & Attribute behaviour?
angular, angular-directive, typescript
Solution
`this.viewContainer.createEmbeddedView` returns `EmbeddedViewRef` that contains `rootNodes`. You can use it to implement your behaviour
@Directive({ selector: '[singleBehaviour]' })
export class SingleBehaviourDirective {
constructor(
private templateRef: TemplateRef<any>,
private _renderer: Renderer2,
private viewContainer: ViewContainerRef) { }
@Input() set singleBehaviour(config: any) {
let view = this.viewContainer.createEmbeddedView(this.templateRef);
let rootElem = view.rootNodes[0];
if(rootElem) {
rootElem.style.visibility = 'hidden';
this._renderer.setProperty(rootElem, 'disabled', true);
}
}
}
Plunker Example
Problem
I am trying to build an Angular Directive where I want to achieve following things based on some config input values - Add element in DOM based on input values. (Just like ngIf) - Add some styling to element if its rendered - Add some attribute properties like `disabled` to element As per my little bit knowledge and understanding of Angular, we can achieve 1st requirement using Structural Directive. Where as for 2nd & 3rd requirement we need to create Attribute Directive. Here is my implementation for both directives ``` import { SomeService } from './some.service'; import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; @Directive({ selector: '[structuralBehaviour]' }) export class StructuralBehaviourDirective { constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef, private someService: SomeService) { } @Input() set structuralBehaviour(config: any) { // 1st Condition // Conditional Stamentents using config and somService // For the purpose to decide whether to add template in // DOM or not this.viewContainer.createEmbeddedView(this.templateRef); } } ``` Here is Attribute Directive ``` import { SomeService } from './some.service'; import { Directive, ElementRef, Input, Renderer } from '@angular/core'; @Directive({ selector: '[attributeBehaviour]' }) export class AttributeBehaviourDirective { constructor(private _renderer: Renderer, private _el: ElementRef, private someService: SomeService) { } @Input() set attributeBehaviour(config: any) { // 2nd Condition // Conditional Stamentents using config and someService // For the purpose to set style visibility property to hidden this._el.nativeElement.style.visibility = 'hidden'; // 3rd Condition // Conditional Stamentents using config and someService // For the purpose to add disabled attribute this._renderer.setElementProperty(this._el.nativeElement, 'disabled, true); } } ``` Currently, I am using above directives like follows which works fine for me ``` <button *structuralBehaviour="config" [attributeBehaviour]="config" class="btn btn-primary">Add</button> ``` What I am looking out here is answer to question, Is it possible to merge both of above directive together and build single directive out of it so that I can use them something like this ``` <button *singleBehaviour="config" class="btn btn-primary">Add</button> ```