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);

Relaterte artikler