Injecting dynamic templates in Angular 7

Let me simplify my issue:

  1. I am currently using NgxDatatable to display a CRUD table.
  2. I have a base component named CrudComponent, which manages all CRUD operations.
  3. This component was designed to be extended for all basic entities.

The challenge I am encountering now is finding a way for child components to somehow inject custom cellTemplate.

I want to avoid duplicating code, so I don't have to repeatedly copy the parent template just to add 1-2 ng-template.

For instance, in CrudComponent:

    @ViewChild('actionsCellRenderer') actionsCellRenderer: TemplateRef<any>;

And in the template:

    <ng-template #actionsCellRenderer let-row="row" let-value="value">
        <button mat-icon-button (click)="startEdit(row)">
            <fa-icon [icon]="['far', 'edit']"></fa-icon>
        </button>
        <button mat-icon-button (click)="startDelete(row)" color="warn">
            <fa-icon [icon]="['far', 'trash-alt']"></fa-icon>
        </button>
    </ng-template>

If I extend this CrudComponent with MovieComponent, I'd have to manually copy the entire HTML template into the new MovieComponent.html file and add:

    @ViewChild('ratingCellRenderer') ratingCellRenderer: TemplateRef<any>;
    <ng-template #ratingCellRenderer let-row="row" let-value="value">
        <bar-rating
                [(rate)]="value"
                [max]="10"
                theme="horizontal"
                readOnly="true"
        ></bar-rating>
    </ng-template>

Potential solutions:

  1. One approach could be utilizing a template pre-compiler like twig. Is this feasible? If so, how?
  2. Or a more Angular-centric solution. Essentially creating a table of TemplateRef<any> instances like this:
cellRenderers = {
   rating: new TemplateRef<any>(), //but how do I manually create TemplateRef?
   picture: new TemplateRef<any>(),
}

Then in the NgxDatatable columns definition:

{name: 'Score', prop: 'score', cellTemplate: this.cellRenderers['rating']},
  1. OR perhaps there's another, more elegant way to address this concern?

Answer №1

After deciding to remove NgxDatatable, I took the initiative to create my own version of CrudTable and integrated a new component called ColumnRendererComponent:

import {Component, ComponentFactoryResolver, Input, OnInit, ViewChild, ViewContainerRef} from '@angular/core';
import {TableColumnType} from '../Table/TableColumnType';
import {FieldConfig} from '../../../Interface/FieldConfig';
import {RendererInterface} from './RendererInterface';
import {PlainRenderer} from './PlainRenderer';
import {FunctionRenderer} from './FunctionRenderer';

@Component({
    selector: 'column-renderer',
    template: `<ng-template #renderer></ng-template>`
})
export class ColumnRendererComponent implements OnInit {
    @Input() public value: any;
    @Input() public row: any;
    @Input() public column: FieldConfig;
    @Input() public columnType: TableColumnType;

    constructor(
        protected componentFactoryResolver: ComponentFactoryResolver,
        public viewContainerRef: ViewContainerRef
    ) {
    }

    ngOnInit(): void {
        this.loadRenderer();
    }

    loadRenderer() {
        let component = this.columnType.template ? this.columnType.template :
            (this.columnType.renderFn ? FunctionRenderer : PlainRenderer);
        let componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);

        let viewContainerRef = this.viewContainerRef;
        viewContainerRef.clear();

        let componentRef = viewContainerRef.createComponent(componentFactory);
        let instance = <RendererInterface>componentRef.instance;
        instance.column = this.column;
        instance.columnType = this.columnType;
        instance.row = this.row;
        instance.value = this.value;
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Managing CORS in Angular2 for REST WebApi calls

Currently, I am utilizing an Angular 2 front end along with a WebApi backend where the WebApi is CORS enabled. var cors = new EnableCorsAttribute("*", "*", "*"); GlobalConfiguration.Configuration.EnableCors(cors); This setup works well with different sit ...

Using Typescript to Define Mongoose Schemas

Currently exploring the creation of a user schema in TypeScript. I've observed that many people use an interface which functions well until I introduce a message involving username.unique or required property. No error code present: import {model, mo ...

The ngbDatepicker within the Bootstrap angular framework is designed to seamlessly integrate with ngbPanelContent without causing overflow issues

I've integrated the ngbDatepicker into a form as shown below <ngb-panel> <ng-template ngbPanelTitle> <div class="row"> <ui-switch (change)="onChange($event,2)" [checked]="profession ...

Strict mode error occurs when attempting to assign a value to ngComponentOutlet that is incompatible with the type of the lazy-loaded component

I am attempting to implement lazy loading for a component in Angular 11 (strict mode) using guidance from this tutorial. Dealing with strict mode has been challenging as there are very few resources available that cater to it. The goal is to have a compon ...

Ways to invoke a slice reducer from a library rather than a React component

I've been working on a React application using the React Boilerplate CRA Template as my foundation. This boilerplate utilizes Redux with slices, which is great for updating state within a React component. However, I'm facing a challenge when try ...

The 'zone' property is not recognized on the 'Observable<{}>' data type

I am currently following the meteor-ionic tutorial and encountering a typescript error: typescript: src/pages/details/details.ts, line: 35 Property 'zone' does not exist on type 'Observable<{}>'. This is my componen ...

What Type of state does Typescript expect in React?

Whenever I attempt to pass the state in my TypeScript-based React application using any to a function, I encounter a tslint error. no-any: The use of 'any' for type declaration compromises type safety. It is recommended to replace it with a mo ...

In Angular 2+, as you loop through an array of objects, make sure to create a new row (<tr>) for each property of the object

I'm currently grappling with a scenario where I need to utilize tables to achieve the following: Array of objects [ { name:'Jhon', email:'<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail=" ...

Having difficulties generating ngc and tsc AOT ES5 compatible code

I've explored various options before seeking help here. I have an angular2 library that has been AOT compiled using ngc. Currently, I am not using webpack and solely relying on plain npm scripts. Below is the tsconfig file being utilized: { "comp ...

Experimenting with Nuxtjs application using AVA and TypeScript

I'm in the process of developing a Nuxt application using TypeScript and intend to conduct unit testing with AVA. Nonetheless, upon attempting to run a test, I encounter the following error message: ✖ No test files were found The @nuxt/typescrip ...

Is it possible to utilize an array of numbers as a data source in ng2-smart table?

Hey there, I'm currently facing an issue with populating ng2-smart-table with an array of numbers. When I try to display the table, all I see is 6 empty rows like this: https://i.stack.imgur.com/DZJjq.png Here's the code for the table: <ng2- ...

Deleting items with a swipe gesture in Angular 10

Hey there, fellow developer! I could really use some assistance in implementing the swipe delete feature for our Angular project. Could you take a look at the screenshot provided below? The code snippet given to me for this feature is as follows: &l ...

Lack of Intellisense in Sveltekit for the generated $types module on WebStorm

Is there a setting in WebStorm to enable intellisense for automatically generated ./$types by SvelteKit? I'm writing without any minimal example, just curious. Everything is done according to SvelteKit's documentation. Using satisfies LayoutLoad ...

Angular: Reacting to events with SVG attributes

Is there a way to access the attribute (e.g. fill) of an SVG object using an Angular event (e.g. mouseenter)? I attempted these different variations but had no success. <rect #rrr [attr.fill]="'green'" (mouseenter)="rrr.fill=&a ...

Discover a component-sharing feature within Angular 2

Currently, I have a page that displays all records in a table with pagination at the bottom. I believe this pagination feature should be an independent component so it can be reused in various management panels such as UserManagement and PostManagement. T ...

Creating asynchronous JavaScript constructors using a static method called "create" presents challenges when dealing with TypeScript types

I've been diving into the world of asynchronous constructors and have successfully implemented them in JavaScript. However, I'm facing a challenge with TypeScript types. Here's how it should ideally work: const a: AnyClass = await AnyClass. ...

What causes the Babel JSON configuration error to appear in my project?

I'm currently working on a React website, utilizing TSX instead of JSX. In my setup, I am using webpack and Babel. However, I have encountered an error while running the webpack-dev-server. ERROR in ./src/index.tsx Module build failed (from ./node_mo ...

Guide for installing the uncompressed version of Angular2 with NPM

Is there a way to install the uncompressed version of Angular2 using NPM? This is how I usually do it: npm install angular2 ...

Transform the MUI Typescript Autocomplete component to output singular values of a specific property rather than a complete object

When utilizing MUI Autocomplete, the generic value specified in onChange / value is determined by the interface of the object set in the options property. For instance, consider an autocomplete with the following setup: <Autocomplete options={top ...

I aim to link a variable in a directive with a component

Each directive comes with its own functionality and specific features. It can be challenging to understand how to connect a variable from a directive to a component. This particular directive involves detecting x-axis and y-axis positions during mouse ev ...