Is it possible to create a single directive that can handle both Structural and Attribute behaviors?

Trying to develop an Angular Directive that will handle various functionalities based on config input values

  1. Dynamically add elements to the DOM based on input values (similar to ngIf)
  2. Apply styling to rendered elements
  3. Add attribute properties such as disabled to elements

Based on my understanding of Angular, we can accomplish the first requirement using a Structural Directive. For the second and third requirements, we need to create an Attribute Directive. Below is the 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) {

        // Handling the logic for adding template in DOM
        this.viewContainer.createEmbeddedView(this.templateRef);

   }
}

Here is the 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) {

        // Applying style visibility property to hidden
        this._el.nativeElement.style.visibility = 'hidden';

        // Adding disabled attribute 
        this._renderer.setElementProperty(this._el.nativeElement, 'disabled', true);

    }
}

Currently, I am using these directives as follows, which is working well

<button *structuralBehaviour="config" [attributeBehaviour]="config"
 class="btn btn-primary">Add</button> 

I'm exploring if it's possible to merge both directives into a single directive for ease of use, something like this

<button *singleBehaviour="config" class="btn btn-primary">Add</button> 

Answer №1

When you call this.viewContainer.createEmbeddedView
, it will provide you with an EmbeddedViewRef that includes the rootNodes. This can be used to define your desired behavior.

@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);
    }
  }
}

Check out this Plunker Example

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Learn how to implement Angular 8 to listen for changes in an observable within an interceptor

Currently, I am in the process of developing an HTTP interceptor that aims to include an 'access level' parameter in the request. The challenge arises when attempting to extract this value from an observable named currentAccessLevel$. Unfortunate ...

Definitions for nested directories within a main index.d.ts

We have developed custom typings for the latest version of material-ui@next and successfully included them in the library during the last beta release. For those interested, you can access the index.d.ts file here. However, there seems to be a problem wi ...

Ensure the inferred type is asserted in TypeScript

Is there a more elegant approach to assert the type TypeScript inferred for a specific variable? Currently, I am using the following method: function assertType<T>(value: T) { /* no op */ } assertType<SomeType>(someValue); This technique prov ...

Error message: Unable to assign value to 'kind' property as it is undefined in Angular Webpack application

Unexpectedly, my Angular application is encountering an error during the build process. TypeError: C:\Users\c\dev\privacy\node_modules\@fortawesome\angular-fontawesome\fesm2020\angular-fontawesome.mjs: Cannot se ...

Dialog component from HeadlessUI doesn't support the Transition feature

Currently working with Next.JS version 14.1.3 I recently integrated the <Dialog> component from HeadlessUI and configured TailwindCSS. However, I encountered an issue where the Modal window doesn't have any transition effects even though I foll ...

Angular Ionic: Unable to compare 'value'. Only arrays and iterable objects are permitted for differentiation

I attempted to display a list value and when I logged the value of the list, it appeared exactly how I wanted: unit value {id: 81, name: "3 BR Suite"} unit value {id: 82, name: "3 BR Grande"} unit value {id: 83, name: "Pool Villa&q ...

Guide for integrating CryptoJS with Angular 2 and TypeScript within a WebPack build setup

Looking for advice on integrating the CryptoJS library with Angular 2 using TypeScript? Many existing resources are outdated and assume the use of SystemJS. Can someone provide straightforward instructions for incorporating CryptoJS with Angular 2 and Type ...

Accept only numerical input, any other type will prompt a notification

Ensuring that users can only input numbers is functioning properly. If a user attempts to enter anything other than a number, an error message should be displayed. I have experimented with Validators and patterns, but I am unable to get the error message ...

Is there a compatibility issue between Nativescript and Angular Universal?

I am fairly new to Nativescript and recently attempted to incorporate Angular Universal building into an existing Angular 9/Nativescript application. However, I encountered the following error: [error] Error: Schematic "universal" not found in collect ...

How to dynamically add a route from an HTTP API to the app-routing.module.ts file in Angular 10

Struggling with an issue while working on Angular 10 version. Despite finding numerous solutions for older versions of Angular, I am still unable to resolve the issue. I consider myself a beginner in Angular as I try to create a website using an Angular c ...

What is the best way to establish communication with the root component in Angular?

I have implemented a modal in the root component that can be triggered from anywhere. However, I am facing a dilemma on how the bottom component can communicate with the top component without excessive use of callback functions. Root Component <contai ...

Do Typescript interfaces check method parameters for validation?

interface optionsParameter { url: string; } function DEC(options: optionsParameter){ } DEC(2) //typescript check compilation error let obj:any = { name: "Hello" } obj.DEC = function(options: optionsParameter){} obj.DEC(1); // no compilation ...

Issue with Angular 4: @HostBinding not properly rendering the CSS class on the host element, resulting in incorrect UI display

My creation of the ProductListComponent allows access to the child component, ProductRowComponent. Please see the code below: ProductListComponent import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import { Product ...

Optimizing Your Angular2 Bundle with Webpack: Best Practices for Minimizing Code Size

I have attempted to include the --optimize-minimize option in my webpack command (version 2.1.0-beta.27), but I am still receiving a bundle.js instead of a bundle.min.js: "build:production": "node_modules/.bin/del-cli public/js/app && node_module ...

Encountering a type error when attempting to filter TypeORM 0.3.5 by an enum column that is

I have the following configuration: export enum TestEnum { A = 'A', B = 'B' C = 'C' } @Entity() export class User { @PrimaryGeneratedColumn() id: number @Column({enum: TestEnum}) test: TestEnum } ...

Enabling output hashing for Django and Angular setup

After setting up my Django and Angular 9 application based on the guidelines in this helpful post: https://medium.com/swlh/django-angular-4-a-powerful-web-application-60b6fb39ef34, I am looking to implement output hashing to prevent caching issues with bro ...

Comparing TypeScript and C++ in terms of defining class reference member variables

class B; class A { A(B b_) : b{b_} {} B &b; }; In C++, it is possible to have a reference member variable like 'b' in class A. Can the same be achieved in TypeScript? Alternatively, is there a specific method to accomplish this in ...

Angular: Issue with canActivate not functioning properly when using redirected routes

My application's router file is set up with the following routes: export const router: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: 'home', canActivate: [AuthGuar ...

How to conceal an element in Angular using its unique identifier

I am looking for a way to toggle the visibility of an element based on its ID. I have a dynamic list with the following structure in my TS component: vehicles = [ { "id": 1, "type": "car", ...

Can you share the appropriate tsconfig.json configuration for a service worker implementation?

Simply put: TypeScript's lib: ['DOM'] does not incorporate Service Worker types, despite @types/service_worker_api indicating otherwise. I have a functional TypeScript service worker. The only issue is that I need to use // @ts-nocheck at t ...