Appearance
Erreur NG0950: Input is required but no value is available yet
L'erreur NG0950 (Input is required but no value is available yet
) est une erreur qui se produit lorsqu'un composant tente d'accéder à un input requis avant qu'une valeur ne lui soit assignée.
Comprendre le problème
Imaginez un interrupteur qui doit recevoir de l'électricité avant de pouvoir fonctionner. De la même manière, certains composants Angular ont besoin de recevoir des données (inputs) avant de pouvoir fonctionner correctement. Si vous essayez d'utiliser ces inputs avant qu'ils ne soient disponibles, Angular affiche cette erreur.
Quand cette erreur se produit-elle ?
Cette erreur se produit généralement lorsque :
- Vous accédez à un input requis trop tôt dans le cycle de vie du composant
- Vous essayez de lire un input requis directement lors de l'initialisation de la classe
- Vous accédez à un input dans le constructeur du composant
Un exemple concret
Voici un exemple de code qui produira cette erreur :
ts
import { Component, input } from '@angular/core';
@Component({
selector: 'app-user-card',
standalone: true,
template: `
<div class="card">
<h2>{{ userName }}</h2>
<p>ID: {{ userId }}</p>
</div>
`,
})
export class UserCardComponent {
// Input requis pour le nom d'utilisateur
userName = input.required<string>();
// Input requis pour l'ID utilisateur
userId = input.required<number>();
// ❌ Erreur : Tentative d'accès à l'input requis avant qu'il ne soit défini
private userNameUpperCase = this.userName().toUpperCase();
}
ts
import { Component } from '@angular/core';
import { UserCardComponent } from './user-card.component';
@Component({
selector: 'app-parent',
standalone: true,
imports: [UserCardComponent],
template: `
<app-user-card [userName]="'Alice'" [userId]="123"></app-user-card>
`,
})
export class ParentComponent {}
Dans cet exemple, nous tentons d'accéder à userName
lors de l'initialisation de la classe pour créer userNameUpperCase
, mais à ce moment, l'input n'a pas encore reçu de valeur du composant parent.
Comment corriger cette erreur
Solution 1 : Utiliser des contextes réactifs
La meilleure approche consiste à utiliser des contextes réactifs, comme computed
ou directement dans le template :
ts
import { Component, computed, input } from '@angular/core';
@Component({
selector: 'app-user-card',
standalone: true,
template: `
<div class="card">
<h2>{{ userName }}</h2>
<p>ID: {{ userId }}</p>
<!-- Accès direct dans le template -->
<small>{{ userName().toUpperCase() }}</small>
</div>
`,
})
export class UserCardComponent {
// Input requis pour le nom d'utilisateur
userName = input.required<string>();
// Input requis pour l'ID utilisateur
userId = input.required<number>();
// ✅ Utilisation de computed pour accéder à l'input de manière réactive
userNameUpperCase = computed(() => this.userName().toUpperCase());
}
Solution 2 : Utiliser les hooks du cycle de vie
Une autre approche consiste à accéder aux inputs dans ngOnInit
ou plus tard dans le cycle de vie :
ts
import { Component, OnInit, input } from '@angular/core';
@Component({
selector: 'app-user-card',
standalone: true,
template: `
<div class="card">
<h2>{{ userName }}</h2>
<p>ID: {{ userId }}</p>
<small>{{ userNameUpperCase }}</small>
</div>
`,
})
export class UserCardComponent implements OnInit {
// Input requis pour le nom d'utilisateur
userName = input.required<string>();
// Input requis pour l'ID utilisateur
userId = input.required<number>();
userNameUpperCase = '';
ngOnInit() {
// ✅ Accès sécurisé car ngOnInit est appelé après l'initialisation des inputs
this.userNameUpperCase = this.userName().toUpperCase();
}
}
ASTUCE
Préférez toujours l'approche réactive avec computed
car elle permettra de maintenir la réactivité si la valeur de l'input change.
Solution 3 : Utiliser un input optionnel avec valeur par défaut
Si l'input n'est pas strictement requis, vous pouvez le rendre optionnel avec une valeur par défaut :
ts
import { Component, input } from '@angular/core';
@Component({
selector: 'app-user-card',
standalone: true,
template: `
<div class="card">
<h2>{{ userName }}</h2>
<p>ID: {{ userId }}</p>
<small>{{ userNameUpperCase }}</small>
</div>
`,
})
export class UserCardComponent {
// Input optionnel avec valeur par défaut
userName = input<string>('Utilisateur');
userId = input.required<number>();
// ✅ Maintenant sécurisé car userName a toujours une valeur
userNameUpperCase = this.userName().toUpperCase();
}
Bonnes pratiques
- N'accédez jamais aux inputs dans le constructeur ou lors de l'initialisation des propriétés de classe.
- Utilisez
computed
pour les transformations des inputs qui doivent rester réactives. - Accédez aux inputs dans
ngOnInit
ou plus tard si vous n'avez pas besoin de réactivité. - Rendez les inputs optionnels avec valeurs par défaut quand c'est approprié.
ATTENTION
Si vous utilisez une ancienne version d'Angular (avant la version 16), vous utiliserez le décorateur @Input()
au lieu de la fonction input()
. Les principes restent les mêmes, mais la syntaxe sera différente.