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