Utilizing a directive in contexts beyond a component

I have developed a popover module that consists of two components and three directives. However, I am encountering an issue where I am unable to utilize the directives outside of the main component. Whenever I try to do so, I face an editor error stating:

No provider for MatPopoverComponent

and a browser error displaying:

ERROR Error: NodeInjector: NOT_FOUND [MatPopoverComponent]

Is there any workaround to enable me to use the directives beyond the component?

The current implementation works as follows:

<mat-popover>
  <mat-popover-content>Some Content</mat-popover-content>
  <button toggle-popover>Click Me</button>
</mat-popover>

However, my desired usage is this:

<mat-popover>
  <mat-popover-content>Some Content</mat-popover-content>
</mat-popover>

<button toggle-popover>Click Me</button>

One of the directives is shown below (all three are identical except for the click event function):

@Directive({
  selector: '[toggle-popover]'
})
export class TogglePopoverDirective {

  public constructor(private el: ElementRef<HTMLElement>, @Host() private popover: MatPopoverComponent) { }

  @HostListener('click')
  public onClick() {
    this.popover.toggle(this.el)
  }
}

This snippet showcases the main component utilizing a directive, errors arise when using it outside of this context:

@Component({
  selector: 'mat-popover',
  templateUrl: './popover.component.html',
  styleUrls: ['./popover.component.scss']
})
export class MatPopoverComponent {

  @ContentChild(MatPopoverContentComponent)
  public content: MatPopoverContentComponent

  public toggle(el: ElementRef<HTMLElement>) {
    this.content.elementRef = el
    this.content.togglePopover()
  }

  public open(el: ElementRef<HTMLElement>) {
    this.content.elementRef = el
    this.content.openPopover()
  }

  public close() {
    this.content.closePopover()
  }
}

Below is the definition of the popover module:

@NgModule({
  imports: [
    CommonModule,
    BrowserModule,
    MatDialogModule
  ],
  bootstrap: [MatPopoverComponent],
  declarations: [
    MatPopoverComponent,
    MatPopoverContentComponent,
    OpenPopoverDirective,
    ClosePopoverDirective,
    TogglePopoverDirective
  ],
  exports: [
    MatPopoverComponent,
    MatPopoverContentComponent,
    OpenPopoverDirective,
    ClosePopoverDirective,
    TogglePopoverDirective
  ]
})
export class MatPopoverModule { }

Answer №1

After making some adjustments, I successfully achieved the desired outcome by eliminating the @Host() decorator and assigning a template reference to the directive. The revised code now appears as follows:

<mat-popover #myPopover>
  <mat-popover-content>Some Content</mat-popover-content>
</mat-popover>

<button [toggle-popover]="myPopover">Click Me</button>
@Directive({
  selector: '[toggle-popover]'
})
export class TogglePopoverDirective {

  @Input('toggle-popover')
  public popover: MatPopoverComponent

  public constructor(private el: ElementRef<HTMLElement>) { }

  @HostListener('click')
  public onClick() {
    this.popover.toggle(this.el)
  }
}

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

What is preventing Bootstrap properties from being applied to HTML elements appended to the DOM through JavaScript?

Currently, I am immersed in a project that utilizes Bootstrap to generate various nested components styled in accordance with Bootstrap's class system. I triumphantly crafted a card component using Bootstrap, but encountered a challenge when attemptin ...

angular change digits to Persian script

I am trying to convert English numbers to Persian numbers in angular 4: persianNumbers = ["۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"]; engli ...

Is there a way to inform TypeScript that an object can only return properties from values found within an array?

I am trying to ensure that the return object from a function in TypeScript only allows keys that correspond to string values present in an array passed as an argument to the function. The returned object should contain a subset of keys from a list of valid ...

Implementing Shader Effects around Mouse using Three.js

Could someone please share tips on how to add a shader effect around the mouse area using Three.js? I'm inspired by the homepage of this website: I'm eager to explore some leads or examples. Thank you in advance! ...

When using RxJS forkjoin, it will cease subscription if there is a flatMap present within one of the observables it is awaiting

I have been experimenting with nested calls using rxjs and trying to implement nested forkJoins. However, I have encountered an issue where the outer forkJoin stops returning a result when there is a flatMap inside the inner observable. Here is a snippet ...

What is the purpose of wrapping my EventEmitter's on function when I pass/expose it?

My software interacts with various devices using different methods like serial (such as USB CDC / Virtual COM port) and TCP (like telnet). To simplify the process, I have created a higher-level interface to abstract this functionality. This way, other sect ...

Encase the event handler within JQuery

Here's an example of inputs with OnBlur event handlers: <input name="abc" tabIndex="5" class="datetime" onblur="if (CheckMode(this))__doPostBack('abc',''); else return false;" /> Now, in JQuery Form ready function, I want ...

Troubleshooting the issue of the background of element A not changing when hovering over element B, despite mouseleave not

Currently, I am attempting to modify the background of element A when mouseover event occurs on element B, and then revert it back to its original state upon mouseleave. It's worth noting that B is nested within A. Strangely, while the background colo ...

Why does the content not appear again when switching between tabs?

Hello! I'm facing an issue with toggling between two sets of content on my page. Initially, the correct content shows up, but when I switch tabs, the new content doesn't appear. Furthermore, if I click back to the first tab, that content disappea ...

Trouble with loading images on Angular Application

After successfully building and deploying my Angular App using the build command on the cli with the deploy-url option as shown below: ng b -deploy-url /portal/ I encountered an issue where everything in the assets folder was showing up as 404 not found ...

Creating a parameterized default route in Angular 2

These are the routes I've set up: import {RouteDefinition} from '@angular/router-deprecated'; import {HomeComponent} from './home/home.component'; import {TodolistComponent} from './todolist/todolist.component'; import { ...

Guide on using jQuery to incrementally cycle through an array using a button

I am facing an issue with iterating through an array of objects using a button. The iteration is skipping 2 on each click instead of moving to the very next record. Can someone help me troubleshoot this problem? Or suggest a better approach to iterate thro ...

Experiencing difficulty accessing the response header in Angular 16 due to CORS restrictions

When attempting to retrieve the response header from my post call, I am encountering difficulties as it appears there are "no headers" or I may be doing something incorrectly. On the backend, I am utilizing ASP.NET Core. Below is a basic outline of my API ...

The Intersection of Material-UI, TypeScript, and Powerful Autocomplete Features

In my TypeScript project, I'm attempting to develop a Material-UI AutoComplete component that retrieves the input value based on an object's property name -> obj[key] However, when using the prop getOptionLabel, I encountered the following er ...

Iterate through each image within a specific div element and showcase the images with a blur effect applied

I have a div with multiple images like this: <div class="am-container" id="am-container"> <a href="#"><img src="images/1.jpg"></img></a> <a href="#"><img src="images/2.jpg"></img>< ...

What causes setInterval to create an endless loop when used inside a while loop in JavaScript?

I attempted to initiate a delayed "one" call or a "one or two?" question, but instead of working as expected, the function continued running indefinitely. Surprisingly, everything worked perfectly fine without using setInterval. quester2() function quest ...

How can I implement a toggle button to display additional details for a specific row within a table created using React.js?

I'm currently working on a project using Next.js and have come across an unexpected issue. Upon reading a JSON file, I populate a table with the data retrieved from it. Each piece of information in the table has hidden details that should only be reve ...

Tips for specifying types in protractor.conf.js while utilizing the @ts-check feature

Within my Angular CLI v7.3.6 project, there is a protractor.conf.js file that I'm looking to enhance with @ts-check in VSCode. When using @ts-check, I aim to execute the browser.getCapabilities() function in the onPrepare() callback but encountered an ...

"The JavaScript code included in the index.html file is not functioning as expected when called in the main.js file within a

Here is the index.html code for a simple VueJS app that includes a widget from netvibes.com. The widget code is added in the html file and functioning properly. <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC " ...

The subscription for the second Observable in RxJS concatMap is triggered individually

I am currently developing an Angular 6 application. I want the app to display a loading animation whenever there is a change in the route or if there are any pending HTTP requests. To achieve this, I have set up two Observables as follows: For httpPendingR ...