【问题标题】:How to display custom angular tag in angular slickgrid custom formatter如何在角度 slickgrid 自定义格式化程序中显示自定义角度标签
【发布时间】:2020-07-21 13:56:42
【问题描述】:

在 angular slickgrid 中,我使用自定义 angular 组件来显示用户信息。可以使用自定义格式化程序显示自定义角度标签。在这里我分享了我的代码 sn-p。

export const CspfmAuditInfoFormatter: Formatter = (row: number, cell: number, value: any, columnDef: any, dataContext: any, grid: any) => {
  return `<ion-buttons>
        <cspfm-audit-info [setIcon]="ios-information-circle-outline" [setIconClass]="" [setInfo]="${dataContext}"></cspfm-audit-info>
    </ion-buttons>`
}; 

cspfm-audit-info 是我自己的角度组件,用于显示数据审计信息。我想显示 cspfm-audit-info。


软件版本

角度:7.3.5

Angular-Slickgrid:2.19.0

打字稿:3.1.6

操作系统:Windows 10

节点:10.16.3

NPM:6.9.0

【问题讨论】:

    标签: angular angular-slickgrid


    【解决方案1】:

    这在 Angular-Slickgrid 中被多次询问,请参阅这些问题 #7#148 以及其他 Stack Overflow 问题 How to render custom angular component instantly in angular slickgrid

    简短的回答是“否”,您不能使用自定义格式化程序来执行此操作,但您可以使用 asyncPostRenderer 来执行此操作,这里是 Wiki - Using Angular Component with asyncPostRenderer,这是带有示例的 Example 22

    但是使用asyncPostRenderer 有很多缺点,我在 Wiki 中写了它们,这里是主要部分:

    首先...为什么我们不能将 Angular 组件与客户格式化程序一起使用?由于 Angular 是如何构建的,它需要一个完整的循环来使用数据渲染组件,但是 SlickGrid Formatter 只需要字符串输出并且它必须立即(同步)并且 Angular 组件只能以异步方式返回(您可以立即返回,但不会填充数据)。这就是它不能使用 Formatter 的原因,但是 SlickGrid 提供了类似于 Formatter 并且以异步方式工作的 asyncPostRender。这样可行,但它有一些缺点,因为它是异步的,所以渲染速度稍慢(您可能会直观地看到它在屏幕上渲染)。尽管如此,使用 jQuery 和/或 HTML 的常规格式化程序仍然是首选方式(至少对我而言)......但是,嘿,如果你真的想使用 Angular 组件,那么它是可能的,只要记住它是异步的,虽然渲染速度稍慢。

    那我就结束了

    更好的解决方案尽可能地使用自定义格式化程序,因为使用 asyncPostRender 的 Angular 组件是 SLOW(你是警告)。它们很慢,因为它们需要一个完整的周期,不能被缓存并且在每行被渲染后渲染(因为它们的异步性质),而自定义格式化程序与行本身同时渲染,因为它们本质上是同步的。

    如果您真的想尝试一下(我几乎可以肯定您在尝试后会改变主意),这里是代码

    import {
      AngularGridInstance,
      AngularUtilService,
    } from 'angular-slickgrid';
    
    export class MyComponent {
      constructor(private angularUtilService: AngularUtilService){ }
      
      initGrid() {
        this.columnDefinitions = [
          {
            id: 'assignee2',
            name: 'Assignee with Angular Component',
            field: 'assignee',
            minWidth: 100,
            filterable: true,
            sortable: true,
            filter: {
              model: new CustomAngularComponentFilter(), // create a new instance to make each Filter independent from each other
              collection: this.assignees,
              params: {
                component: FilterNgSelectComponent,
              }
            },
            queryFieldFilter: 'assignee.id', // for a complex object it's important to tell the Filter which field to query and our CustomAngularComponentFilter returns the "id" property
            queryFieldSorter: 'assignee.name',
    
            // loading formatter, text to display while Post Render gets processed
            formatter: () => '...',
    
            // 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 = {
          enableAsyncPostRender: true, // for the Angular PostRenderer, don't forget to enable it
          asyncPostRenderDelay: 0,    // also make sure to remove any delay to render it
        };
      }
    
      renderAngularComponent(cellNode: HTMLElement, row: number, dataContext: any, colDef: Column) {
        if (colDef.params.component) {
          const componentOutput = this.angularUtilService.createAngularComponent(colDef.params.component);
          Object.assign(componentOutput.componentRef.instance, { item: dataContext });
    
          // use a delay to make sure Angular ran at least a full cycle and make sure it finished rendering the Component
          setTimeout(() => $(cellNode).empty().html(componentOutput.domElement));
        }
      }
    }
    

    结论

    Final Word,它很慢,我从来没有亲自使用过,但是如果你希望渲染速度很慢,这是可行的……我的用户当然不希望这样,所以我从不使用它们。

    【讨论】:

    • 感谢您的信息@ghiscoding。但我已经在我的应用程序中尝试了 asyncPostRender。角度组件的渲染会给用户带来一些不好的体验。所以我试图通过自定义格式化程序显示我的角度组件。
    • 好吧,我已经说过这是 only 的方法,我解释了为什么(主要是因为 Angular 需要一个完整的周期来渲染),自定义格式化程序需要一个字符串输出马上(同步),而 Angular 永远不会给你那个(异步)......除非 Angular 有某种魔法可以以同步的方式做到这一点,但我真的很怀疑。你可能不喜欢这个答案,但这是唯一可行的方法,这就是我从不使用 Angular 标签的原因
    • 顺便说一句,如果您找到了在自定义格式化程序中执行此操作的方法,那么请告诉我,我很乐意使用此类代码更新我的 Wiki 和演示。我不认为这是可能的,但有人可能已经找到了一种方法......如果是这样,我想知道。
    • 当然@ghiscoding
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-19
    • 2017-08-03
    • 2017-08-24
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    相关资源
    最近更新 更多