Je veux accéder à l'élément actuel dans lequel le tuyau est utilisé. Est-ce possible dans Angular?
Le tuyau est utilisé comme suit, par ex. <input type="text" value="'my-translation-key' | translate" />
Voici un exemple du tuyau réel
@Pipe({
name: 'translate',
pure: false
})
export class TranslatePipe implements PipeTransform {
transform(key: string, params?: ITranslationSelector): string {
// 1. Get the value by key
// 2. Return the value
// What I want as well:
// this.el.nativeElement.dataset.translationKey = key;
// Where el is current element where pipe is used
}
}
3 réponses
Deux solutions possibles en fonction de votre faisabilité:
- Créez une variable de référence de modèle et envoyez-la en tant que paramètre à votre Pipe personnalisée.
Où se trouve le tuyau personnalisé
export class CustomPipe implements PipeTransform {
transform(key: string, params: any): string {
//Here param is your input element
return 'your_value';
}
Mais dans cette approche, vous obtenez un élément d'entrée dans un tube personnalisé en tant qu'élément HTML qui peut ne pas répondre à vos besoins.
Récupérez l'élément d'entrée en tant que ViewChild dans votre composant, puis transmettez-le au tuyau personnalisé
@ViewChild ('inputRef') inputElementRef: ElementRef;
Dans ce tuyau personnalisé sera:
export class CustomPipe implements PipeTransform {
transform(key: string, params: any): string {
//Here param is your input element
return 'your_value';
}
Grâce à cela, vous pouvez travailler facilement, mais cette approche est meilleure si vous n'avez qu'un ou deux éléments dans un seul modèle, car la récupération de plusieurs View Child ne sera pas un code propre, même si cela fonctionnera correctement.
Je voudrais partager quelques tentatives qui ne m'ont pas conduit à la solution souhaitée, mais qui pourraient peut-être amener quelqu'un d'autre à la faire fonctionner. Aussi une autre idée qui n'a pas encore été mentionnée.
Accrochez-vous au pipeline de création de modèles
Une autre façon pourrait être de s'accrocher au modèle créant un pipeline angulaire.
Idée: Obtenez l'AST et vérifiez la classe de tuyau, injectez la référence de l'élément et placez-la en tant que paramètre (comme mentionné précédemment par d'autres).
Par exemple, comme ces gars-là l'ont fait: https://github.com/typebytes/ngx-template- flux
Tentatives:
Avec pure: true
, il n'y a qu'une seule classe de canal d'instance créée par composant.
Avec pure: false
, une classe de canal d'instance est créée pour chaque utilisation du canal dans le HTML de vos composants.
Vous pouvez injecter elementRef: ElementRef
dans le constructeur du tube, mais vous n'obtiendrez que la référence au composant dans lequel le tube est utilisé (dans les deux cas).
J'ai pensé que cela pourrait peut-être fonctionner d'une manière ou d'une autre avec une autre directive injectée dans le tuyau qui fait référence au HTMLElement.
Exemple:
<my-component>
<div>{{'foo' | mypipe}}</div>
<div>{{'foo' | mypipe}}</div>
<input type="text" [value]="'bar' | mypipe">
<input type="text" [value]="'bar' | mypipe">
</my-component>
J'ai essayé de créer une directive pour obtenir une référence pour les HTMLElements habituels qui ressemblaient à ceci:
@Directive({
selector: 'input,div,span'
})
export class ElementRefDirective {
constructor(public readonly elementRef: ElementRef) {}
}
Mais je n'ai pas pu l'injecter dans la classe MyPipe, ni l'inverse (obtenir le MyPipe injecté dans la directive).
Vous pouvez également utiliser une variable de référence de modèle. Modèle:
<input #inputEl type="text" value="'my-translation-key' | translate: inputEl" />
La partie du fichier Pipe ts:
export class TranslatePipe implements PipeTransform {
transform(key: string, element?: any): string {
// Element was marked by #inputEl template variable.
element.dataset.translationKey = key;
}
}
Questions connexes
De nouvelles questions
angular
Questions sur Angular (à ne pas confondre avec AngularJS), le framework web de Google. Utilisez cette balise pour les questions angulaires qui ne sont pas spécifiques à une version individuelle. Pour l'ancienne infrastructure Web AngularJS (1.x), utilisez la balise angularjs.