I'm writing a table component that will need to be very open to modification for my company. And i decided to go for this:
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>
In table.ts (just the interesting code):
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);
}
the injectable is like this
@Injectable()
export class ColumnConf {
resource: Resource;
accessors: Accessors;
}
accessors is a custom type i created to keep it readable:
export interface Accessors {
[key: string]: (resource: Resource) => string | number;
}
and with this code, I can use the ngTemplateOutlet, pass custom value for column by row , put specific configuration to draw a component each time. But I also need my columns to be interactives.
trouble is: I can't use this to display component with some states, for example this one:
@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 {}
}
It got a drop down menu, but it redraw immediately without keeping it state, so i can't keep it open. Any idea how to do so ?
I thought about ngtrack, but it didn't seem to work. Also tried to change the change detection strategy no luck either.
It seems it redraw every time, when i click anywhere on the screen, anf i want it to not or keep it state. Any ideas on how to do so?
Find a solution, Turned out you should not create injector on the fly in the template, I now create the injectors directly when i get the API such as