typescript - Rendera Angular-komponenter i Handsontable-celler


I ett av mina projekt försöker jag visa Angular-komponenter (som en autokompletterande rullgardinsökning) i en tabell. På grund av de krav jag har (som att kunna markera flera olika celler med ctrl+klick) bestämde jag mig för att prova med handsontable.

Jag har använt handsontable-renderaren och lagt till komponenterna dynamiskt.

Koden ser ut så här

matrix.component.ts

this.hot = new Handsontable(this.handsontable.nativeElement, {
  data: this.tableData,
  colWidths: [80, 300],
  colHeaders: ['Id', 'Custom Component'],
  columns: [
    {
      data: 'id',
    },
    {
      data: 'id',
      renderer: (instance: any, td: any, row: any, col: any, prop: any, value: any, cellProperties: any) => {
        if (cellProperties.hasOwnProperty('ref')) {
          (cellProperties.ref as ComponentRef<CellContainerComponent>).instance.value = row;
        } else {
          cellProperties.ref = this.loadComponentAtDom(
            CellContainerComponent,
            td,
            ((component: any) => {
              component.template = this.button4Matrix;
              component.value = row;
            }));
        }
        return td;
      },
      readOnly: true,
    },
  ],
});


private loadComponentAtDom<T>(component: Type<T>, dom: Element, onInit?: (component: T) => void): ComponentRef<T> {
  let componentRef;
  try {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
    componentRef = componentFactory.create(this.injector, [], dom);
    onInit ? onInit(componentRef.instance) : console.log('no init');
    this.appRef.attachView(componentRef.hostView);
  } catch (e) {
    console.error('Unable to load component', component, 'at', dom);
    throw e;
  }
  return componentRef;
}

Mitt nuvarande problem är livscykeln för de renderade Angular-komponenterna.

Saker jag försökte:

  1. Gör ingenting

Försökt lösning: Att göra ingenting och lämna allt till Angular

Problem: Angular anropar aldrig ngOnDestroy för CellContainer.

  1. Sparar componentRefs

Försökt lösning: Spara componentRef i en array och efter ett visst antal renderingar försöka förstöra de komponenter jag renderade för ett tag sedan. Räkna via tid, handsontable-hooks (verticalScroll/beforeRender/afterRender), i render-metoden

Problem: Att förstöra Angular-komponenten ger alltid ett fel ('kan inte läsa egenskapen 'nativeNode' av null') eller så visas komponenterna helt fel

  1. Kontrollera under rendering om ett element finns där

Försökt lösning: Under renderingen: Jag kontrollerade om det redan finns en komponent och om det gjorde det använde jag att återanvända den redan existerande komponenten genom att bara lägga till ett nytt värde.

Problem: Värdena blir helt blandade vid bläddring.

En länk till min lösning (och en implementerad lösning #3) finns på GitHub.

Har någon en idé om hur man hanterar detta på ett smidigt sätt? Om inte blir applikationen långsam och oanvändbar efter lite rullning och användning av tabellen. Bättre referens: https://handsontable.com/docs/8.2.0/tutorial-cell-function.html

Svar #1

Använder en cell-renderare. Använd det renderarens namn du vill när du konfigurerar kolumnen:

const container = document.getElementById('container');

const hot = new Handsontable(container,
 {
  data: someData,
  columns: 
[{
    renderer: 'numeric'
  }]

});

Svar #2

kanske behöver du prova changeDetection som nedan, vilket tvingar fram de nya förändringarna i din komponent.

changeDetection: ChangeDetectionStrategy.OnPush

Relaterade artiklar