Templates on dynamically added fields are not populating.

Hello Team,

I am trying to use template binding on dynamically added column on ejs-grid. Unfortunately this is not working. 

My grid initially does not loading all the columns later when I am fetching data for the grid, that data tells which are the dynamic columns and the data as well. After getting that data I am pushing the dynamic columns in a loop and providing the data for the grid as well.

Doing that, columns are populating fine and data as well but when I am going to apply template for some column(which is added later), that is not working.

My data object is as follows

{

        "date": null,

        "rating_1": null,

        "form_id": 14,

        "last_name": "Charlie",

        "textarea": null,

        "toggle": null,

        "page_id": 466,

        "submission_date": "12/07/2021",

        "attachment": "https://api.kpmdev.one//rest/downloadattachment?id=zRKFclne9FUSTWozGug60NC6qih5ZXUgox3%2FtLEtKr4%3D,https://api.kpmdev.one//rest/downloadattachment?id=zRKFclne9FV0EJbnZTi6MBYNmgLuzJ%2BXXNk%2FR1WyuJM%3D,https://api.kpmdev.one//rest/downloadattachment?id=zRKFclne9FWUsfwx%2FfLQ953mnbbpXuMFtWRibwKsQq4%3D,https://api.kpmdev.one//rest/downloadattachment?id=zRKFclne9FVnG5TFNu9cFLRqzdHcfHDQvI%2F%2BW%2B0C7Sg%3D",

        "page_name": "Page 2",

        "first_name": "Richi",

        "rating_2": null

      }

Of which I am trying to replace the attachment data with  document icon via template and I am using following code for that 

<e-column field='{{item.name}}' *ngIf="item.name == 'attachment'">
          <ng-template #template let-data> 
                        Attachment
          </ng-template>
 </e-column>

But this is clearly failing as its is showing the actual attachment node value instead of the value "Attachment".

So can you please suggest me what is wrong there.

 


5 Replies

SK Sujith Kumar Rajkumar Syncfusion Team August 17, 2021 12:56 PM UTC

Hi Apurba, 
 
Greetings from Syncfusion support. 
 
Based on the provided information we could understand that you are facing problem with rendering template for dynamic columns and we suspect that you are using ngFor for generating the columns. So we suggest you to define template for the dynamic columns by defining the column template separately and then accessing and setting it to the column’s template property as demonstrated in the below code snippets, 
 
app.component.html 
<ejs-grid #grid [dataSource]='data'> 
    <e-columns> 
        <e-column *ngFor="let item of columnName" [field]="item.field" [headerText]='item.headerText' [isPrimaryKey]="item.isPrimaryKey" [template]="item.template"></e-column> 
    </e-columns> 
</ejs-grid> 
<ng-template #colTemplate let-data> 
    <div> 
        <a rel='nofollow' href=https://en.wikipedia.org/wiki/{{data.ShipCountry}}>{{data.ShipCountry}}</a> 
    </div> 
</ng-template> 
 
app.component.ts 
@ViewChild('colTemplate', { static: true }) 
public template: TemplateRef<{}>; 
 
ngOnInit(): void { 
    this.columnName = [ 
             ... 
      { 
        field: 'ShipCountry', 
        headerText: 'Ship Country', 
        template: this.template 
      } 
    ] 
} 
 
We have prepared a sample based on this for your reference. You can find it below, 
 
 
Please get back to us if you require any further assistance. 
 
Regards, 
Sujith R 



AD Apurba Dutta August 24, 2021 02:28 PM UTC

Thanks for the reply

But unfortunately the above solution is not working for me. I have one one parent component which fetches the data and populates the columns dynamically, The code there is

const colRes = (data.customData.data2[0] && data.customData.data2[0].field_details)? JSON.parse(data.customData.data2[0].field_details) : [];

                  this.masterConfig.data_config.columns = Object.assign([],this.masterCols);

                  let totalAddedCols = 0;

                  colRes && colRes.forEach((colItem,index) => {

                    let tempColObj:any = {

                      "name": (colItem.config && colItem.config.submission_parameter)?colItem.config.submission_parameter:colItem.field_id,

                      "caption": (colItem.field_id == "attachment" || colItem.field_id == "toggle" || colItem.field_id == "rating" || colItem.field_id == "image" || colItem.field_id == "checkbox")?colItem.config.submission_parameter:colItem.field_label

                    };

                    if(colItem.field_id == "number" || colItem.field_id == "rating"){

                      tempColObj.dataType = 'number';

                      tempColObj.format = 'N2';

                    }

                    if(colItem.field_id == "date"){

                      tempColObj.dataType = 'Date';

                      tempColObj.format = 'dd/MM/yyyy';

                    }


                    if(colItem.field_id == "attachment"){

                      tempColObj.template = this.attachmentTemplate;

                    }

                    let visibility = true;

                    if(this.masterConfig.data_config.dynamicFields){

                       if(this.masterConfig.data_config.dynamicFields.visible !== undefined){

                        visibility = this.masterConfig.data_config.dynamicFields.visible;

                       }

                       if(this.masterConfig.data_config.dynamicFields.width !== undefined){

                        tempColObj.width = this.masterConfig.data_config.dynamicFields.width;

                       }

                       if((this.masterConfig.data_config.dynamicFields.column_limit !== undefined) && ((totalAddedCols+1)>this.masterConfig.data_config.dynamicFields.column_limit)){

                        visibility = false;

                       }

                    }

                    tempColObj.visible = visibility;


                    this.masterConfig.data_config.columns.push(

                      tempColObj

                    );

                    totalAddedCols++;

                  });

where  attachmentTemplate comes from 

@ViewChild('attachmentTemplate', { static: true })

  public attachmentTemplate: TemplateRef<{}>;

and in the same component view

<ng-template #attachmentTemplate let-data>

        <div>

            <a rel='nofollow' rel='nofollow' href='https://en.wikipedia.org'>{{data}}</a>

        </div>

    </ng-template>

And the child component where I bind the grid, I bind the template as

<ng-container *ngFor="let item of masterConfig.data_config.columns">

                <e-column

                    field='{{item.name}}'

                    headerText='{{item.caption}}'

                    textAlign='{{item.textAlign}}'

                    type="{{item.dataType}}"

                    format="{{item.format}}"

                    [allowResizing]="(item.allowresizing === false)?false:true"

                    displayAsCheckBox="{{item.displayAsCheckBox}}"

                    [showInColumnChooser]="(item.showInColumnChooser === false)?false:true"

                    [visible]="(item.visible === false)?false:true"

                    width='{{item.width?item.width:"auto"}}'

                *ngIf="item.name != 'attachment' && item.dataType != 'icon'"></e-column>


                <e-column field='{{item.name}}' *ngIf="item.name == 'attachment'" [template]="item.template">

                </e-column>

                <e-column field='{{item.name}}' headerText='{{item.caption}}' width='{{item.width?item.width:"auto"}}' *ngIf="(item.dataType == 'icon') && (item.icon_class == 'property')">

                    <ng-template #template let-data>

                        <a rel='nofollow' target="_blank" rel='nofollow' href="{{data.property_url}}">

                            <i class="la la-home" aria-hidden="true" style="font-size: 22px !important;"></i>

                        </a>

                    </ng-template>

                </e-column>

                <e-column field='{{item.name}}' headerText='{{item.caption}}' width='{{item.width?item.width:"auto"}}' *ngIf="(item.dataType == 'icon') && (item.icon_class == 'email')">

                    <ng-template #template let-data>

                        <a rel='nofollow' target="_blank" rel='nofollow' href="{{data.email_url}}">

                            <i class="la la-envelope" aria-hidden="true" style="font-size: 22px !important;"></i>

                        </a>

                    </ng-template>

                </e-column>

                <e-column field='{{item.name}}' headerText='{{item.caption}}' width='{{item.width?item.width:"auto"}}' *ngIf="(item.dataType == 'icon') && (item.icon_class == 'document')">

                    <ng-template #template let-data>

                        <a rel='nofollow' target="_blank" rel='nofollow' href="{{data.document_url}}">

                            <i class="la la-file" aria-hidden="true" style="font-size: 22px !important;"></i>

                        </a>

                    </ng-template>

                </e-column>

            </ng-container>


But this is not working it is showing the actual column data.




SK Sujith Kumar Rajkumar Syncfusion Team August 25, 2021 12:33 PM UTC

Hi Apurba, 
 
Based on the provided information we could understand that you are updating the columns property dynamically after Grid render is completed and so we suspect that the reported problem might be occurring because of the columns not getting regenerated properly. 
 
So for your case, we suggest you to directly set the dynamic column object to the Grid’s columns property as demonstrated in the below code snippet to resolve the problem, 
 
setTimeout(function () { 
    var cols = [...]; 
    cols.forEach(col => { 
        if (col.field == "ShipCountry") { 
            col.template = this.template; 
        } 
    }) 
    this.gridObj.columns = cols; 
}.bind(this), 500); 
 
We have also prepared a sample based on this for your reference by dynamically updating the column object in a time out function. Please find the sample below, 
 
 
If we misunderstood your use case, then please elaborate on it and if possible share us a problem replication sample or try reproducing it in the above shared sample. This would be helpful to identify your exact problem case so that we can validate further based on that. 
 
Regards, 
Sujith R 



AD Apurba Dutta August 27, 2021 12:58 PM UTC

Thanks again for reply.

Still I am facing issues. As my grid is already loaded with some predefined static columns, when I am just assigning new set of columns to that grid after timeout (as you suggested), it is not refreshing the columns. So I have done 

this.grid.refreshColumns(); ​after assigning the updated column list. But this time I lost all the column format I had. Like Date, Number Etc.

So Is there any work around for that.


Currently my grid showing like this

Here you can see that attachment column is now bound with the template correctly but formatting for date column is missing. But when I am doing console of the update grid columns, I can see that the date column has type "Date" and format "dd/MM/yyyy" which was working fine previously.



MS Manivel Sellamuthu Syncfusion Team August 30, 2021 09:59 AM UTC

Hi Apurba, 

Thanks for your update. 

Based on your update, we can understand that with the provided solution column templates are properly loaded but column format is not working properly. By default Column type can be specified using the columns.type property.  

To proceed further on this query could you please share the below details 

  1. Share the complete Grid code
  2. Share the currentView records for the Grid. In Grid current view records can be obtained using getCurrentViewRecords method. Please refer the below code example for more information.
this. grid.getCurrentViewRecords() 

In EJ2 Grid, all the Grid actions like Filtering, Sorting, Grouping, etc., are performed based on the values in the dataSource. If you want to perform Filtering, Sorting on Date column, the values should be DateObject format in its dataSource.  
  1. In your update you have mentioned that after calling refreshColumns method the format for number columns also removed. Please share the current view records for that number column also.
  2. If possible, please share the issue reproducible sample

Regards, 
Manivel 


Loader.
Up arrow icon