javascript - Sende data til og fra en ComponentPortal i Angular CDK
Jeg har prøvd å bruke metoden som finnes på Angular CDK: Hvordan sette Inputs i en ComponentPortal, men PortalInjector ser ut til å være utdatert, uten faktiske instruksjoner om hva man skal gjøre i stedet. Advarselsen om utdatert funksjon sier å "Bruke Injector.create i stedet," men ikke hvordan eller hvor man skal bruke det eller hva det faktisk erstatter.
Jeg har også prøvd å skjønne Materials egen Dialog-komponent for å se om jeg kunne finne ut hvordan de gjorde det, men ingenting.
Så jeg stiller spørsmålet igjen for Angular 13:
Hvordan kan jeg sende data inn i og ut av en komponent som ble opprettet ved hjelp av ComponentPortal()? Hvis svaret er noe generelt som å bruke en Injector, kan du være så snill å vise meg et eksempel eller dokumentasjon på hvordan man gjør dette? En 'hello world' for å sende Injectors?
Svar #1
Åpenbart er jeg sen til festen, men du kan faktisk bruke @Input() og @Output() til komponenten som vises inne i en Portal. Det er ikke åpenbart ved første øyekast, men å kalle this.overlayRef.attach(MyComponent) vil returnere ComponentRef<MyComponent>. Så ut fra det kan du ganske enkelt få direkte tilgang til komponentforekomsten, og deretter gjøre hva du måtte trenge med den.
Slik:
const componentPortal = new ComponentPortal(MyComponent);
const componentRef = this.overlayRef.attach(componentPortal);
// pass data via Input:
componentRef.instance.someInput = 'test';
// subscribe to output:
componentRef.instance.someOutput.subsribe();
Og MyComponent ville se slik ut:
@Component({...})
export class MyComponent {
@Input()
someInput: string;
@Output()
someOutput = new EventEmitter<string>();
}
God koding!
Svar #2
Jeg er litt sent ute til festen, men her er faktisk et annet alternativ som bruker Injector.create.
Først definerte jeg en injeksjonstoken:
export const DATA_INJECTION_TOKEN = new InjectionToken<string>('DATA_INJECTION_TOKEN');
I mitt tilfelle har jeg en tjeneste som håndterer oppretting og levering av ComponentPortal. Som ser omtrent slik ut:
export class FooService {
// ...
open(component: ComponentType<any>, data?: unknown) {
// ...
const portal = new ComponentPortal(
component,
null,
Injector.create({
providers: [{ provide: DATA_INJECTION_TOKEN, useValue: data }],
}),
);
// ...
}
}
Deretter brukte @Inject() for å hente dataene.
export class FoobarComponent {
constructor(@Inject(DATA_INJECTION_TOKEN) data: MyDataType) { }
}
Og til slutt, når man kaller tjenesten som skal generere portalen, så det slik ut:
const data = {foo: 'bar'};
fooService.open(FoobarComponent, data);
