Exploring the Applications of Directives in Multiple Modules within Angular 2

When I declare the directive in two modules, I get an error that says

Type PermissionDirective is part of the declarations of 2 modules
. However, when I declare it in only one module, I receive an error stating
Can't bind to 'isPermission' since it isn't a known property of 'button'
. What could be causing this issue?

I would appreciate it if you could take a look at my app structure.

permission.directive.ts

import { Directive, Input } from '@angular/core';
import { TemplateRef, ViewContainerRef } from '@angular/core';
import { LoginInfoService } from '../service/auth.service';

@Directive({ selector: '[isPermission]' })
export class PermissionDirective {
  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
    private _auth: LoginInfoService
  ) {
  }
  @Input() set isPermission(_module_action: Array<string>) {
    let permission = this._auth.isPermission(_module_action[0], _module_action[1]);
    if (permission) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    } else {
      this.viewContainer.clear();
    }
  }
}

layout.route.ts

import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LayoutComponent } from './layout.component';

const layoutRoutes: Routes = [
   {
      path: '',
      component: LayoutComponent,
      children: [
         {
            path: '',
            loadChildren: () => import('app/dashboard/dashboard.module').then(m => m.DashboardModule),
         },
         {
            path: 'users',
            loadChildren: () => import('app/users/users.module').then(m => m.UsersModule),
         }
      ]
   }
];

export const layoutRouting: ModuleWithProviders = RouterModule.forChild(layoutRoutes);

layout.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PermissionDirective } from 'app/common/directives/permission.directive';

@NgModule({
  imports: [
    CommonModule,
    layoutRouting
  ],
  exports:[],
  declarations: [
    PermissionDirective
  ],
  providers:[]
})
export class LayoutModule { }

dashboard.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
...
import { PermissionDirective } from 'app/common/directives/permission.directive';

@NgModule({
  imports: [
    CommonModule,
    dashboardRouting,
    ....
  ],
  declarations: [
    DashboardComponent,
    PermissionDirective
  ],
  providers: []

})
export class DashboardModule { }

SharedModule

import { NgModule, Optional, SkipSelf, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
.........
import { PermissionDirective } from 'app/common/directives/permission.directive';

@NgModule({
  imports:      [ 
    ....
  ],
  declarations: [ 
    ....
    PermissionDirective
  ],
  exports:      [ 
   ...
    PermissionDirective,
    ...
  ],
  providers:    [  
    ...
  ]
})
export class SharedModule { 
  constructor (@Optional() @SkipSelf() parentModule: SharedModule, private dateAdapter:DateAdapter<Date>) {
    if (parentModule) {
      throw new Error(
        'SharedModule is already loaded. Import it in the AppModule only');
    }
    this.dateAdapter.setLocale('en-in'); // DD/MM/YYYY
  }
}

Answer №1

One effective approach would be to create a shared module that incorporates the directive. Subsequently, you can easily import this module into your desired modules as shown below:

shared.module.ts

@NgModule({
  exports: [PermissionDirective],
  declarations: [PermissionDirective]
})
export class SharedModule {}

Then, proceed to import SharedModule into your target modules:

@NgModule({
  imports: [
    CommonModule,
    dashboardRouting,
    SharedModule
  ],
  declarations: [
    DashboardComponent
  ],
  providers: []
})
export class DashboardModule { }


@NgModule({
  imports: [
    CommonModule,
    layoutRouting,
    SharedModule
  ],
  exports:[],
  declarations: [
  ],
  providers:[]
})
export class LayoutModule { }

Answer №2

To make your Directive accessible throughout the entire project, declare it in the parent module (app.module.ts) and export it.

@NgModule({
  ....
  exports: [CustomDirective]
})
export class AppModule { }

Answer №3

I made a modification by removing some code from the shared module.

import { NgModule, Optional, SkipSelf, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
.........
import { PermissionDirective } from 'app/common/directives/permission.directive';

@NgModule({
  imports:      [ 
    ....
  ],
  declarations: [ 
    ....
    PermissionDirective
  ],
  exports:      [ 
   ...
    PermissionDirective,
    ...
  ],
  providers:    [  
    ...
  ]
})
export class SharedModule { 
// The following code has been removed
/* 
  constructor (@Optional() @SkipSelf() parentModule: SharedModule, private dateAdapter:DateAdapter<Date>) {
    if (parentModule) {
      throw new Error(
        'SharedModule is already loaded. Import it in the AppModule only');
    }
    this.dateAdapter.setLocale('en-in'); // DD/MM/YYYY
  }
*/
}

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

Is it possible to simultaneously play several one-shot sound effects on mobile web browsers?

I'm attempting to trigger a sound effect when the user clicks a button on my web application. Initially, I experimented with this approach: var sound = new Audio("soundeffect.ogg"); function clickHandler(){ sound.play(); } Unfortunately, if the ...

How can the background color of a DIV be altered based on the values of an array's minimum

Basically, I am fetching values from an array using AJAX. The background color will change from green to red based on the "aht_value". Currently, the colors are displaying correctly because I hardcoded the values in the calculation below. However, I want t ...

Sharing State with a Secure Route in Vue Router (using the script setup method)

Hello everyone, I'm encountering an issue while trying to send a state to the protected routes in vue-router. The error that I faced mentioned "Discarded invalid param(s) "_id", "dish_name", "description", "img" ...

Storing retrieved data in React without using Redux involves using either the Context API or

When using Redux, I have a common store where fetched data is stored. For example, if I navigate away from my videos page (/videos) and then return to it, the videos are still available in the videos reducer. This allows me to show the user already loaded ...

Share your ES module (.mjs) on NPMJS with support for Node versions older than 8.5.0 (Dual Package)

In the past, publishing a module written in ES6 to NPMJS was a simple process: transpile the code using Babel and publish the resulting `lib` directory to NPMJS while keeping the original `src` files on GitHub. However, with Node v8.5.0's experimenta ...

Having difficulty displaying a partial view within a view while making an AJAX call

Trying to figure out what's missing in my code. I have a view with some radio buttons and I want to display a different partial view when a radio button is selected. Here's the snippet of my code: Controller public ActionResult Method(string va ...

Exploring the Array Functionality in React

Is there a way to access the lista and add up all the values in unidades when the Producto matches both 1 and 2? [{ "id": "3WzFN", "cliente": "1", "lista": [{ "unidades": "2 ...

Error: The React Material-UI modal is encountering a type error where it cannot access the property 'hasOwnProperty' of an undefined value

Whenever I include a modal in one of my classes, I encounter this error. Error: Unable to access property 'hasOwnProperty' of undefined Here is a simple example where I am attempting to display a basic modal at all times. Any suggestions? I h ...

Generate Array of Consecutive Dates using JavaScript

My array contains the following values (for example): [ 1367848800000: true, 1367935200000: true, 1368021600000: true, 1368108000000: true, 1368194400000: true, 1368367200000: true, 1368540000000: true, 1 ...

The component "SafeAreaViewRN" could not be located within the UIManager

Upon attempting to open a bundle on my Android device, I encountered the following error message: A warning was displayed stating that the app was accessing a hidden field in android's view accessibility delegate. Additionally, an Invariant Violati ...

Styles are not applied by Tailwind to components in the pages folder

NextJS project was already created with tailwind support, so I didn't have to set it up myself. However, when I add className to an HTML element in a component within the pages/ folder, it simply doesn't work, even though the Elements panel in D ...

Algorithm for File Naming

Given an array of desired file names in the order of their creation, where two files cannot have the same name. If a file has a duplicate name, it will be appended with (k), where k is the smallest positive integer that creates a unique name. Output an ar ...

What is the best way to modify or revise meta fields for individual products in order to retrieve multiple images for each product in Shopify?

What is the process for updating or editing meta fields to display multiple images of each product on Shopify? ...

Saving the current $index from an ng-repeat loop to a database row (with row numbers 1.1, 1.2, 1.3) using AngularJS

Currently, I am developing the index page functionality for a book. i.e : 1.1 1.1.1 1.2 1.2.1 In this setup, 1.1 and 1.2 are the parent ng-repeats, while 1.1.1 and 1.2.1 are the child ng-repeats. My goal is to store these numbers ( ...

What is the best way to attach an attribute to a element created dynamically in Angular2+?

After reviewing resources like this and this, I've run into issues trying to set attributes on dynamically generated elements within a custom component (<c-tabs>). Relevant Elements https://i.stack.imgur.com/9HoC2.png HTML <c-tabs #mainCom ...

Tips for invoking a service from another in angular version 6

The following code snippet showcases Service 1, specifically the uploadAttachment method which executes an http post call. This method is invoked from Service 2. However, in Service 2, the instance of Service 1 is consistently undefined, resulting in a fai ...

Combining Extjs combo with autocomplete functionality for a search box, enhancing synchronization capabilities

When using autocomplete search, I've encountered an issue. If I type something and then make a mistake by deleting the last character, two requests are sent out. Sometimes, the results of the second request come back first, populating the store with t ...

Discover the best practices for implementing services within the import decorator of an angular module configuration

Is there a way to access a service inside the load module in Angular, especially when the module is loaded from a decorator and the service is not yet DI? You can refer to this answer for an example. For instance, if the method in the service returns an ...

Tailoring information to fit selected preferences

Currently working on developing a fitness app with Vue, aiming to create personalized workout routines based on user preferences. Users can choose specific options and generate a workout plan by clicking a button. The collected data is stored as an object ...

Ensuring Form Validity with jQuery for Exclusive Radio Buttons

How can I display an error message when a radio button value is not equal to a specific value? I have a series of yes/no questions and want to show disclaimers under each set of buttons if the value provided is null or different from what is required. Most ...