Search code examples
angularbootstrap-4slickgrid

Angular-slickgrid custum Formatter - bootstrap ngbTooltip not working


I am using angular-slickgrid in my angular application with bootstrap 4. I am using custum formatter for one column say detail as below:

Custum formatter code in (cusum.formatter.ts file):

export const detailFormatter: Formatter = (row: number, cell: number, value: any, columnDef: Column, dataContext: any, grid?: any) => {
const template = `<button ngbTooltip="Details" class="btn btn-outline-secondary mr-2 btn-floating btn-blue-grey btn-sm"><i class="fa fa-info"></i></button>`;
return template; }

below is code for using the above custum formatter in angular-silkgrid :

 this.columnDefinitions = [{formatter: detailFormatter,  id: 'detail', name: '', field: 'detail', minWidth: 50,width: 50, maxWidth: 50}, ....other columns}

On running the application I have checked that I am unable to see the tootip 'Details'. So the problem is that bootstrap ngbTooltip is not working with custum formatter in angular-slickgrid.


Solution

  • Note that I'm the author of Angular-Slickgrid.

    You cannot use Angular directly in a Formatter, the reason is because this lib is a wrapper of a javascript/jQuery library and a formatter requires a synchronous function that returns a string (in html format) right away and Angular does not return right away, you need at least 1 cycle before it returns.

    The answer is in this Demo and the code for the Component. You need to use an asyncPostRender

    Taking code sample from that demo

    export class MyComponent implements OnInit {
      prepareGrid() {
        this.columnDefinitions = [
          {
            id: 'assignee2',
            name: 'Assignee with Angular Component',
            field: 'assignee',
            filterable: true,
    
            // to load an Angular Component, you cannot use a Formatter since Angular needs at least 1 cycle to render everything
            // you can use a PostRenderer but you will visually see the data appearing,
            // which is why it's still better to use regular Formatter (with jQuery if need be) instead of Angular Component
            asyncPostRender: this.renderAngularComponent.bind(this),
            params: {
              component: CustomTitleFormatterComponent,
              angularUtilService: this.angularUtilService,
              complexFieldLabel: 'assignee.name' // for the exportCustomFormatter
            },
            exportCustomFormatter: Formatters.complexObject,
          }
        ]; 
    
        this.gridOptions = {
          asyncEditorLoading: false,
          enableAsyncPostRender: true, // for the Angular PostRenderer, don't forget to enable it
          asyncPostRenderDelay: 0,    // also make sure to remove any delay to render it
        };
      }
    }
    

    However, I strongly suggest you to consider using a plain html javascript Custom Formatters. The reason is because is simple, since a Formatter with Angular is defined as async, they are much slower (you will see them loading/rendered in the grid since it takes a cycle to render).

    It works but yeah I strongly suggest to reconsider using only plain html Formatters (event though I added a demo, I never use Angular Formatters).