Angular: предотвратить повторный рендеринг компонента внутри него

Я пишу компонент таблицы, который должен быть очень открытым для модификации для моей компании. И я решил пойти на это:

table.component.html

      <tbody>
  <tr *ngFor="let resource of results">
    <td *ngFor="let col of columns">
      <ng-container *ngComponentOutlet="col.component; injector: createInjector(resource, col.accessors)"></ng-container>
    </td>
  </tr>
</tbody>

В table.ts(просто интересный код):

        results: any[];



createInjector(resource: Resource, accessors: Accessors) {
    const columnConf = new ColumnConf();
    columnConf.resource = resource;
    columnConf.accessors = accessors;
    const options = {
      providers: [{ provide: ColumnConf, useValue: columnConf }],
      parent: this.injector,
    };
    return Injector.create(options);
  }

Инъекция такая

      @Injectable()
export class ColumnConf {
  resource: Resource;
  accessors: Accessors;
}

accessors — это пользовательский тип, который я создал, чтобы он был удобочитаемым:

      export interface Accessors {
  [key: string]: (resource: Resource) => string | number;
}

и с этим кодом я могу использовать ngTemplateOutlet, передавать пользовательское значение для столбца за строкой, задавать определенную конфигурацию для каждого отрисовки компонента. Но мне также нужно, чтобы мои колонки были интерактивными.

проблема в том, что я не могу использовать это для отображения компонента с некоторыми состояниями, например этого:

      @Component({
  selector: 'col-actions',
  template: `
    <div ngbDropdown class="d-inline-block">
      <button type="button" class="btn btn-outline-primary" id="{{ id }}" ngbDropdownToggle>
        Toggle dropdown
      </button>
      <div ngbDropdownMenu [attr.aria-labelledby]="id">
        <button ngbDropdownItem>Action - 1</button>
        <button ngbDropdownItem>Another Action</button>
        <button ngbDropdownItem>Something else is here</button>
      </div>
    </div>
  `,
  styles: [],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ActionsComponent implements OnInit {
  id = Math.floor(Math.random() * 10000 + 1);
  constructor() {}

  ngOnInit(): void {}
}

У него есть выпадающее меню, но оно сразу же перерисовывается без сохранения состояния, поэтому я не могу держать его открытым. Любая идея, как это сделать?

Я думал о ngtrack, но это не сработало. Также безуспешно пытался изменить стратегию обнаружения изменений.

Кажется, он перерисовывается каждый раз, когда я нажимаю в любом месте экрана, и я хочу, чтобы этого не было, или чтобы он сохранял свое состояние. Любые идеи о том, как это сделать?

1 ответ

Найдите решение. Оказалось, что вам не следует создавать инжектор на лету в шаблоне, теперь я создаю инжекторы напрямую, когда получаю API, например

        this.itemsToDisplay = [];
    let i = 0;
    this.results.forEach((resource) => {
      this.itemsToDisplay[i++] = this.columns.map((column) => {
        return {
          resource: resource,
          injector: this.createInjector(resource, column.accessors),
          column: column,
        };
      });
Другие вопросы по тегам