Reputation: 290
I have taken this as an example: Hierachical grid
So I am trying to insert whole html
snippet dynamically but struggling. Inserting right into DOM
doesn't seem to work. innerHTML
property also does not help. I have found out this Dynamic hooks for angular which I've been trying to use as so:
<div class="grid__wrapper">
<ngx-dynamic-hooks [content]="grid_html"></ngx-dynamic-hooks>
</div>
I have defined my grid html
in typescript:
export class UsersGridComponent implements OnInit {
public years = 10;
public localdata: any[];
public col: IgxColumnComponent;
public pWidth: string;
public nWidth: string;
public singers: any[];
data: SafeHtml;
constructor(private sanitizer: DomSanitizer) {
this.singers = SINGERS;
this.localdata = this.singers;
this.data = this.sanitizer.sanitize(SecurityContext.HTML, this.grid_html);
}
ngOnInit(): void {}
grid_html: any = `<igx-hierarchical-grid
IgxPreventDocumentScroll
class="hierarchicalGrid"
[data]="localdata"
(columnResized)="onResize($event)"
[autoGenerate]="false"
[height]="'480px'"
[width]="'100%'"
[rowHeight]="'65px'"
#hierarchicalGrid
>
<igx-column field="Artist" [resizable]="true"></igx-column>
<igx-column field="Photo" [resizable]="true" [minWidth]="'115px'">
<ng-template igxCell let-cell="cell">
<div class="cell__inner_2">
<img [src]="cell.value" class="photo" />
</div>
</ng-template>
</igx-column>
<igx-column
field="Debut"
[resizable]="true"
[minWidth]="'88px'"
[maxWidth]="'230px'"
dataType="number"
[formatter]="formatter"
></igx-column>
<igx-column
field="GrammyNominations"
header="Grammy Nominations"
[resizable]="true"
></igx-column>
<igx-column
field="GrammyAwards"
header="Grammy Awards"
[resizable]="true"
></igx-column>
<igx-column
field="Sales"
header="Album Sales in last {{ this.years }} years"
[width]="'230px'"
[filterable]="false"
>
<ng-template igxCell let-val>
<igx-sparkline
height="40px"
width="220px"
[dataSource]="val"
valueMemberPath="Copies"
displayType="Line"
lineThickness="2"
brush="rgb(255,102,0)"
>
</igx-sparkline>
</ng-template>
</igx-column>
<igx-row-island [height]="null" [key]="'Albums'" [autoGenerate]="false">
<igx-column field="Album" [resizable]="true"></igx-column>
<igx-column
field="LaunchDate"
header="Launch Date"
[resizable]="true"
[dataType]="'date'"
></igx-column>
<igx-column
field="BillboardReview"
header="Billboard Review"
[resizable]="true"
></igx-column>
<igx-column
field="USBillboard200"
header="US Billboard 200"
[resizable]="true"
></igx-column>
<igx-row-island [height]="null" [key]="'Songs'" [autoGenerate]="false">
<igx-column field="Number" header="No." [resizable]="true"></igx-column>
<igx-column field="Title" [resizable]="true"></igx-column>
<igx-column
field="Released"
dataType="date"
[resizable]="true"
></igx-column>
<igx-column field="Genre" [resizable]="true"></igx-column>
</igx-row-island>
</igx-row-island>
<igx-row-island [height]="null" [key]="'Tours'" [autoGenerate]="false">
<igx-column field="Tour" [resizable]="true"></igx-column>
<igx-column
field="StartedOn"
header="Started on"
[resizable]="true"
></igx-column>
<igx-column field="Location" [resizable]="true"></igx-column>
<igx-column field="Headliner" [resizable]="true"></igx-column>
</igx-row-island>
</igx-hierarchical-grid>`;
public onResize(event) {
this.col = event.column;
this.pWidth = event.prevWidth;
this.nWidth = event.newWidth;
}
public formatter = (a) => a;
}
I have imported necessary modules:
const componentParsers: Array<HookParserEntry> = [
{ component: IgxHierarchicalGridComponent },
{ component: IgxColumnComponent },
{ component: IgxRowIslandComponent },
];
@NgModule({
declarations: [UsersGridComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxHierarchicalGridModule,
IgxSparklineCoreModule,
IgxSparklineModule,
DynamicHooksModule.forRoot({ globalParsers: componentParsers }),
],
providers: [],
bootstrap: [UsersGridComponent],
})
export class UsersGridModule {}
Currently I am receiving errors
Is there something I can do to fix this or is it more likely impossible to achieve? Thanks
Upvotes: 0
Views: 476
Reputation: 1635
Not super familiar with ngx-dynamic-hooks
, but I reproduced the errors trying your code alright. They (at least the first one I debugged) are from initializing the column components which are looking to inject their parent Grid(token), but are instead initialized with the same injector from the containing view (UsersGridComponent
) so it can't be found. In reality, Angular creates injectors in hierarchy so the Grid's will be the parent injector for the columns and so on. It's technically possible to get the injector of the dynamically created grid and pass it down, but not sure if that's something that can be configured through ngx-dynamic-hooks
or if it's not supported at all as a scenario.
So I'll answer the original question with an alternative suggestion: Angular has some API to dynamically create components, see Dynamic component loader, however it's very geared towards generating a single component rather than a full nested markup (the latter can be achieved through multiple creates for each child, but it will be prohibitively complicated IMHO). So, a much simpler path, with minimal changes to the original sample:
<ng-template #anchor></ng-template>
ViewContainerRef
and use it's API to create a dynamic component containing the grid as need. You can expose public properties of said component that can internally re-configure the grid as needed, for this example changing the years for the Sparkline column:
export class AppComponent {
@ViewChild('anchor', { static: true, read: ViewContainerRef })
private anchor!: ViewContainerRef;
public loadGrid() {
const componentRef = this.anchor.createComponent(HGridColumnResizingSampleComponent);
componentRef.instance.years = 15;
}
}
Running example: https://stackblitz.com/edit/angular-yxfn7c?file=src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.component.ts
Upvotes: 1
Reputation: 1587
Have you treid injecting the IGX_GRID_BASE injection token, from where you can access the interface describing the common grid type
constructor(@Host() @Optional() @Inject(IGX_GRID_BASE) private grid: IgxGridBaseDirective) {
}
/**
* Prevents scrolling the page, when mouse wheel over the grid body.
*/
private preventDocumentScroll(event) {
event.preventDefault();
}
private getGridTBody(): HTMLElement {
return this.grid.tbody.nativeElement;
}
There is an example that we are using to define our own scrolling handler and prevent some functionalities on certain criterias.
Available here: https://github.com/IgniteUI/igniteui-angular-samples/blob/master/src/app/directives/prevent-scroll.directive.ts
Upvotes: 0