Unable to utilize directives that are declared within the app module in child modules when using Angular 6

Currently utilizing Angular 6.

I've established a custom directive named StickyPopover by extending NbgPopover and have integrated it into the declaration of app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { AuthLayoutComponent } from './layouts/auth-layout/auth-layout.component';
import {AdminLayoutComponent} from './layouts/admin-layout/admin-layout.component';
import {FormsModule} from '@angular/forms';
import {RouterModule} from '@angular/router';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
import {StickyPopoverDirective} from './sticky-popover.directive';


@NgModule({
  declarations: [
    AppComponent,
    AuthLayoutComponent,
    AdminLayoutComponent,
    StickyPopoverDirective           // custom created directive
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    FormsModule,
    HttpClientModule,
    RouterModule,
    NgbModule.forRoot(),
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule { }

The location of the directive exists at the same level as that of the app.module.ts file.

The content of sticky-popover.directive.ts is as follows:

import {
  ElementRef,
  Directive, Input, TemplateRef,
  EventEmitter,
  Renderer2,
  Injector,
  ComponentFactoryResolver,
  ViewContainerRef,
  NgZone, OnInit, OnDestroy
} from '@angular/core';

import { NgbPopover, NgbPopoverConfig } from '@ng-bootstrap/ng-bootstrap';

@Directive({
  selector: '[appStickyPopover]',
  exportAs: 'stickyPopover'
})
export class StickyPopoverDirective extends NgbPopover implements OnInit, OnDestroy {
  @Input() stickyPopover: TemplateRef<any>;

  popoverTitle: string;

  placement: 'auto' | 'top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' |
    'bottom-right' | 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | ('auto' | 'top' | 'bottom' |
    'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'left-top' | 'left-bottom' |
    'right-top' | 'right-bottom')[];

  triggers: string;

  container: string;

  shown: EventEmitter<{}>;

  hidden: EventEmitter<{}>;

  ngpPopover: TemplateRef<any>;

  canClosePopover: boolean;

  toggle(): void {
    super.toggle();
  }

  isOpen(): boolean {
    return super.isOpen();
  }



  constructor(
    private _elRef: ElementRef,
    private _render: Renderer2,
    injector: Injector,
    componentFactoryResolver: ComponentFactoryResolver,
    private viewContainerRef: ViewContainerRef,
    config: NgbPopoverConfig,
    ngZone: NgZone
  ) {
    super(_elRef, _render, injector, componentFactoryResolver, viewContainerRef, config, ngZone, document);
    this.triggers = 'manual';
    this.popoverTitle = 'Permissions';
    this.container = 'body';
  }

  ngOnInit(): void {
    super.ngOnInit();
    this.ngbPopover = this.stickyPopover;

    this._render.listen(this._elRef.nativeElement, 'mouseenter', () => {
      this.canClosePopover = true;
      this.open();
    });

    this._render.listen(this._elRef.nativeElement, 'mouseleave', (event: Event) => {
      setTimeout(() => { if (this.canClosePopover) { this.close(); } }, 100);

    });

    this._render.listen(this._elRef.nativeElement, 'click', () => {
      this.close();
    });
  }

  ngOnDestroy(): void {
    super.ngOnDestroy();
  }

  open() {
    super.open();
    const popover = window.document.querySelector('.popover');
    this._render.listen(popover, 'mouseover', () => {
      this.canClosePopover = false;
    });

    this._render.listen(popover, 'mouseout', () => {
      this.canClosePopover = true;
      setTimeout(() => { if (this.canClosePopover) { this.close(); } }, 0);
    });
  }

  close() {
    super.close();
  }

}

I have a module called SavedSearches, which is imported within the AdminModule, declared in the app.module.ts

When I try to use the StickyPopover directive within the template of the SavedSearches module like this:

<i class="fa fa-plus-circle" aria-hidden="true" appStickyPopover [popoverTitle]="additional" [autoClose]="true" data-placement="right"></i>

An error occurs stating:

can't bind to 'popoverTitle' since it isn't a known property of i

If I move the directive inside the SavedSearches module and include it in the saved-searches.module.ts declaration, it works without errors. However, using it in other modules results in:

StickyPopovoerDirective is a part of the declaration of 2 modules. Move it in the upper module which imports these two modules.

Answer №1

If you want the directive to be accessible in modules other than AppModule, you can create a SharedModule. Simply add the StickyPopoverDirective to the declarations and exports within the SharedModule.

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

Once this is done, import the SharedModule into your other modules and utilize the directive as needed.

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

A guide to sending parameters in the URL body using TypeScript for a REST API on the Ionic framework

As a novice in Ionic and TypeScript, I am facing an issue with accessing an API. The API can only be accessed using the POST method with parameters passed in the body for security reasons. I need to retrieve JSON data from this API but I'm unsure how ...

Obtaining the Enum key in Angular using the Enum type instead of a string value

Is there a way to retrieve the key of an enum not as a string, but with the enum itself? https://stackblitz.com/edit/typescript-av8rkx enum Widgets { Foo = "this is foo", Bar = "this is bar" } const current = "this is foo" ...

What is the best way to display data retrieved through an HTTP service using ngFor?

I was attempting to inject a service (contact.service.ts) into a component (contact-list.component). The service contains data on employees defined in contacts.ts. While I was able to successfully receive the data, I encountered difficulty in rendering it ...

Observing with starting value

When using an observable, I am trying to filter and display a list. The input event is only fired when the user starts typing, so initially the list is not displayed. How can I set a default value for the observable this.filterLocation$ until the input eve ...

Webpack and incorporating bespoke scripts

Can someone please help me understand how webpack works? I'm currently working on an Angular 2 project with a webpack starter and I have some JavaScript scripts from AWS (my SDK for API Gateway). These are about 10 JS files that I currently have liste ...

Getting data from the previous view upon clicking the browser's back button in Angular while navigating to a different view

I am facing an issue in my Angular application where I am trying to set up multiple views using routing. However, when I navigate to another view and then press the browser's back button, the previous view data is not retained and the page refreshes c ...

ng serve is consistently experiencing issues due to the absence of exported members

I am new to Angular and struggling with where and how to ask questions or effectively search for answers. Any guidance would be greatly appreciated. Currently, I am facing the following issue: After running npm install in my application, when I try to ru ...

What is the process for including the Node_modules folder in a GitHub repository?

I'm facing a challenge with pushing my Angular project to GitHub's remote server. While I can successfully push all the folders, the node_modules folder, which is large and contains numerous files, is not getting pushed. It seems that including t ...

Unable to import Express in Angular

In my Angular app, there are no syntax errors present. Within a file titled test1.js, I have only one line of code: var express = require('express'); However, I am encountering an error in my log: (Interestingly, commenting out this single l ...

Sending information to a module imported by Angular

I'm facing a dilemma regarding how to efficiently pass data to an imported module in my App. Essentially, I've crafted a module packed with various components that are utilized in my application. My goal is to provide this module with two key d ...

Trigger Angular Animation when there is a modification in the DOM element's appearance or styling

I've been working on implementing a fade-in animation in my Angular App that triggers every time the background changes, but I'm facing some challenges with it. Here's the relevant code snippet: HTML: <div @fadeIn [style.backgroundImag ...

Can you explain the meaning of `images:Array<Object> = [];` in TypeScript?

Recently, I stumbled upon this code snippet in TypeScript images:Array<Object> = []; I'm curious, what exactly does the "<>" notation signify? ...

Typescript raises a error notification regarding the absence of a semicolon when importing a JSON module

Attempting to import a local JSON object into my Vuex store using const tree = import('@/articles/tree.json');. The setting "resolveJsonModule": true, has been enabled in my tsconfig.json and it loads successfully, however NPM is flooding the out ...

Angular 7: Implementing a Dynamic Search Filtering System

I'm looking to create a versatile filter in Angular 7 that can perform search operations on any field across multiple screens. Custom pipe filters I've come across only seem to work with specific static fields, limiting their use. Let me provide ...

Buttons for camera actions are superimposed on top of the preview of the capacitor camera

I am currently using the Capacitor CameraPreview Library to access the camera functions of the device. However, I have encountered a strange issue where the camera buttons overlap with the preview when exporting to an android device. This issue seems to on ...

Data not reflecting changes in component when field is modified?

I currently have a table on my web page that displays data fetched from an array of objects. The data is collected dynamically through websockets by listening to three different events. User can add an entry - ✅ works perfectly User can modify ...

Translation of menu item label has not been executed

Here we have a component called SidebarMenuComponent that is not translating the labels of its menu items correctly. The goal is to get the labels translated, but the current implementation is failing. What is the correct approach to apply translation in t ...

Having trouble retrieving values from Promise.allSettled on Node.js 12 using TypeScript version 3.8.3

Currently, I am delving into NodeJs 12 and exploring the Promise.allSettled() function along with its application. The code snippet that I have crafted allows me to display the status in the console, but there seems to be a hitch when attempting to print t ...

Error: No routes found in Angular 5

I have developed an Angular 5 app and set up the following routing configuration in app-routing.module.ts file: import { ControlPanelComponent } from './dashboard/control-panel/control-panel.component'; import { MainComponent } from './dash ...

@nrwl/node:build: Tips for customizing the generated output file name

I've been working on a project in a nx monorepo that involves Angular CLI and a Node backend. In my angular.json file, I have a custom webpack configuration to adjust the filename of the bundle. When I run ng build app (which triggers @nrwl/node:build ...