I'm learning Angular.
I want to create custom directive, but doesn't work ! (it's not app for production, it's a discover app ^^)
I have no error, the project build ! But the directive don't work !
To create the directive, I use : ng generate directive directive-name
Can you help me to resolve my problem ?
The code :
Component - app.component.ts
import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { POKEMONS } from './mock-pokemon-list';
import { Pokemon } from './pokemon';
import { AppModule } from './app.module';
@Component({
selector: 'app-root',
standalone: true,
imports: [
RouterOutlet,
AppModule
],
templateUrl: 'app.component.html',
styles: [],
})
export class AppComponent implements OnInit {
pokemonList: Pokemon[] = POKEMONS;
pokemonSelected: Pokemon|undefined;
ngOnInit(): void {
console.log(this.pokemonList);
}
selectPokemon(pokemonId: string) {
const id: number = +pokemonId;
const pokemon: Pokemon|undefined = this.pokemonList.find(pokemon => pokemon.id == id);
if(pokemon) {
console.log(`Vous avez cliqué sur le pokémon ${pokemon.name}`);
this.pokemonSelected = pokemon;
} else {
console.log(`Vous avez demandé un pokémon qui n'existe pas.`);
this.pokemonSelected = pokemon;
}
}
}
Template - app.component.html
<h1 class="center" >Liste de pokémons</h1>
<input
#input
(keyup.enter)="selectPokemon(input.value)"
type="number"
/>
@if(pokemonSelected) {
<p>Vous avez sélectionné le pokémon : {{ pokemonSelected.name }}</p>
}
@else {
<p>Aucune correspondance.</p>
}
<div class="container" >
<div class="row" >
@for (pokemon of pokemonList; track pokemon) {
<div class="col s12 m4 s6">
<div class="card horizontal" appBorderCard>
<div class="card-image">
<img [src]="pokemon.picture">
</div>
<div class="card-stacked">
<div class="card-content">
<p class="header">{{ pokemon.name }}</p>
<p><small>{{ pokemon.created }}</small></p>
</div>
</div>
</div>
</div>
} @empty {
<p>Aucun élément dans la base.</p>
}
</div>
</div>
<router-outlet />
The directive - border-card.directive.ts
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[appBorderCard]'
})
export class BorderCardDirective {
constructor(private el: ElementRef) {
this.setHeight(180);
this.setBorder("#f5f5f5");
}
@HostListener('mouseenter') onMouseEnter() {
this.setBorder("#009688");
}
@HostListener('mouseleave') onMouseLeave() {
this.setBorder("#f5f5f5");
}
private setHeight(height: number) {
this.el.nativeElement.style.height = `${height}px`;
}
private setBorder(color: string) {
this.el.nativeElement.style.border = `solid 4px ${color}`;
}
}
Module - app.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BorderCardDirective } from './border-card.directive';
@NgModule({
declarations: [],
imports: [
CommonModule,
BorderCardDirective
]
})
export class AppModule { }
The stack :
Angular CLI: 17.3.2
Node: 21.6.2 (Unsupported)
Package Manager: npm 10.5.0
Angular:
...
Package Version
------------------------------------------------------
@angular-devkit/architect 0.1703.2 (cli-only)
@angular-devkit/core 17.3.2 (cli-only)
@angular-devkit/schematics 17.3.2 (cli-only)
@schematics/angular 17.3.2 (cli-only)
Thanks for advance
Approach 1:
standalone: truedirective
app.component
Approach 2:
Ensure that the directive is not set to
standalone: trueimport { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({ selector: '[appBorderCard]', }) export class BorderCardDirective { ...
Add the directive to the declarations and exports array of the app.module.ts, only if we export the directive, it will be visible to app.component.ts
app.module.ts
If you are using standalone app component, Please ensure you have imported the directive on the app.components imports array! Since we are adding to the imports array, we need to set
standalone: trueon the@Directive({selector: 'some selector', standalone: true })object of the directive file!If you are using modular approach, also same thing ensure
app.module.tshas the directive added to thedeclarationsarray if its not standalone, or to theimportsarray if its standalone!If not imported then angular, will take
appBorderCardas an HTML attribute and will not throw an error!So, if the component/directive is standalone and used in a module, it belongs on the
importsarray, if not it belongs on thedeclarationsarrayWhen using the standalone approach, we are limited to using only standalone true
component/directivewith them being added to theimportsarray!