javascript - Consolidarea a două directive într-una singură
Să presupunem că cineva are două directive predefinite dir1 și dir2 (care sunt furnizate de un API terț asupra căruia nu are control). Să spunem că acestea pot fi aplicate unui element HTML după cum urmează:
<div dir1="red" [dir2]="123">... My Content ...</div>
Am observat că aplic directivele de mai sus cu aceleași valori de legare exact în mai multe locuri din codul meu. În loc să mă repet, aș dori să creez propria mea directivă personalizată, să o numesc myDir, pe care să o pot aplica astfel:
<div MyDir >... My Content ...</div>
Acesta ar trebui să fie exact la fel ca aplicarea dir1 și dir2 așa cum în exemplul anterior de mai sus, adică va avea valorile "red" și 123 codificate direct în clasa sa.
Am încercat să configurez legăturile gazdei așa cum este în exemplul Plunker următor, dar asta nu funcționează..
O idee pe care o am este că, dacă TypeScript ar avea moștenire multiplă, atunci aș scrie pur și simplu clasa MyDir ca o extensie a Dir1 și Dir2..
Întrebarea mea este cum să procedezi pentru a scrie directiva personalizată (MyDir) pentru a atinge utilizarea dorită?
Vă rog să mă ajutați, vă mulțumesc!
https://plnkr.co/edit/W20Wvew326qsGfPU5H6v
Răspuns #1
Actualizare: Încă nu este posibil în mai 2020. Este pe lista de funcționalități a echipei Angular. Urmăriți progresul aici https://github.com/angular/angular/issues/8785
(TL;DR. Pentru soluția mea hack, vezi Plunker aici)
Următorul este ceea ce a ajuns să fie soluția mea pentru problemă, așa cum a fost prezentată mai sus. Rețineți că aceasta nu este cea mai generală soluție; în alte scenarii, adaptabilitatea sa va depinde în mare măsură de modul în care arată API-ul public al directivelor implicate. Ar trebui să funcționeze bine acolo unde directivele care urmează a fi combinate au cel puțin ElementRef ca una dintre dependențele de injectare, astfel:
constructor(private elRef: ElementRef, /*...*/) { /*...*/ }
Acesta poate fi cu siguranță cazul dacă directivele sunt responsabile pentru schimbarea stilului unui element.
Ceea ce am făcut a fost să creez pur și simplu două obiecte new Dir1/Dir2 trecând ElementRef al MyDir ca context pentru Dir1/Dir2 astfel:
// inside MyDir constructor
this.d1 = new Dir1(this.elRef, /*...*/);
this.d2 = new Dir2(this.elRef, /*...*/);
Apoi setez proprietățile publice (@Input bindings) ale d1/d2 la valorile pe care am nevoie să le aibă permanent (pentru a evita să mă repet):
//inside MyDir constructor
this.d1.dir1 = "red";
this.d2.dir2 = 123;
Apoi, tot ce a trebuit să încerc să fac a fost să potrivesc metodele publice d1/d2 cu MyDir prin invocarea metodelor primelor în interiorul metodei/metodelor corespunzătoare ale celei din urmă, de exemplu.
ngAfterContentInit() {
this.d1.ngAfterContentInit();
this.d2.ngAfterContentInit();
}
Iată plunker-ul cu toate acestea puse împreună https://plnkr.co/edit/TCagW8vOPrqSiOT9Oztf
Răspunsul #2
Începând cu Angular 15, poți folosi API-ul de compoziție a directivelor. Ceea ce cauți este să adaugi directive la o altă directivă
Exemplul tău va fi:
@Directive({
hostDirectives: [Dir1, Dir2],
})
export class MyDir {
dir1 = inject(Dir1, { self: true });
}
