Data in column template

Hi,

I need to display different contents in a grid column based on analyzing the data in the row.

I have three attributes in the data object for a row: NoteRead (value is a string, which could be Yes, No or Unknown), NoteReadDate, and NoteNotNeeded (boolean).

If there is a NoteReadDate, I want to display it. But if there is no date and NoteNotNeeded is true, I want to display 'Not needed.'

If there is no date and NoteNotNeeded is false, I want to show the value of NoteRead.

I can build the actual template and v-if statements. 

But how do I access the data for the row within the template? Is the data object sent as a prop, or in some other way?

Thanks in advance for your help.

7 Replies 1 reply marked as answer

BS Balaji Sekar Syncfusion Team September 23, 2020 02:50 PM UTC

Hi Tom, 
 
Greetings from the Syncfusion support. 
 
Query: How do I access the data for the row within the template? 
 
Based on your query we suspect that you need to display the different contents in the column based on the row data. In our sample we have bound the row data to the template column(OrderID) based on “v-if” condition. 
 
Using column.template feature, you can bind your own component in the Grid’s column with condition basis. Please refer the below code example and sample for more information. 
 
[App.Vue] 
 
<ejs-grid :dataSource="data" ref="gridObj" width="600px"> 
      <e-columns> 
        <e-column 
          field="OrderID" 
          headerText="Order ID" 
          :isPrimaryKey="true" 
          width="120" 
          :template="orderIDTemplate" 
          textAlign="Right" 
        ></e-column> 
        <e-column 
          field="OrderDate" 
          type="date" 
          width="120" 
          format="dd/MM/yyyy" 
          headerText="Start Date" 
        ></e-column> 
        <e-column field="Status" headerText="Status" width="100"></e-column> 
      </e-columns> 
    </ejs-grid> 
 
export default { 
  data() { 
    return { 
      data: gridData, 
      orderIDTemplate: function() { 
        return { 
          template: Vue.component("columntemplate", { 
            template: `  <div v-if="data.Status === 'allowed'" class="template_checkbox"> 
             <span>{{data.OrderID}}</span> 
                </div> 
                <div v-else-if="data.Status === 'excluded'" class="template_checkbox"> 
                    <span>{{data.EmployeeID}}</span> 
                </div> 
                <div v-else-if="data.Status === 'forbidden'" class="template_checkbox"> 
                    <span>{{data.CustomerID}}</span> 
                </div>` 
          }) 
        }; 
      } 
    }; 
  }, 
  methods: {}, 
  provide: { 
    grid: [Page] 
  } 
}; 
 
 
 
Please find the documentation of column.template feature from the below link 
 

Please get back to us, if you need further assistance. 

Regards, 
Balaji Sekar. 


Marked as answer

TM Tom McNeer September 24, 2020 07:19 PM UTC

Thank you for your help.

I understand the creation of the column template with its row data from the grid. But within the template, I need to create methods (from button clicks) that can be emitted to the parent template that wraps the grid. How can I tell the parent element to listen for the event?

When adding a child template within a basic Vue template, one might do:
<child-template
  @myEvent = 'doSomething'
>
</child-template>

Then the parent would fire doSomething(). How can I achieve the same thing when creating the component instance this way? Or for that matter, if I create a custom component for the template:

customTemplate: function {
   return { template : columntempVue}
}

... how can I listen for an event emitted from that component?

Thanks in advance for your help?


MS Manivel Sellamuthu Syncfusion Team September 25, 2020 02:00 PM UTC

Hi Tom, 

Greetings from Syncfusion support. 

We suggest to use Vue Global Event Bus concept to achieve this requirement. By default this EventBus allows us to emit an event from one component and listen for that event in another component. So we can easily communicate with two Vue components by using this EventBus concept. In the below code we have showed how to use this concept to achieve your requirement, 

Parent Component: 
 
<template> 
  <div id="app"> 
    <ejs-grid :dataSource="data" ref="grid" :created="created"> 
 . . . 
    </ejs-grid> 
  </div> 
</template> 
<script> 
import Vue from "vue"; 
import { GridPluginPageToolbarEdit } from "@syncfusion/ej2-vue-grids"; 
import { gridData } from "./data"; 
import { closest } from "@syncfusion/ej2-base"; 
import ChildComponent from "./child"; 
 
Vue.use(GridPlugin); 
Vue.prototype.$eventHub = new Vue(); 
export default { 
  components: { 
    ChildComponent, 
  }, 
  data() { 
    return { 
      shipCountry: "", 
      data: gridData, 
    }; 
  }, 
  methods: { 
    colTemplate: function () { 
      return { template: ChildComponent }; 
    }, 
    createdfunction (args) { 
// here we are listening the click event 
      this.$eventHub.$on("communicate"this.getRowDetails); 
    }, 
    getRowDetailsfunction (e) { 
// based on the click event we are showing the row details here. 
      let rowObj = this.$refs.grid.ej2Instances.getRowObjectFromUID( 
        closest(e.target, ".e-row").getAttribute("data-uid") 
      ); 
      let data = rowObj.data; 
      alert(JSON.stringify(data)); 
    }, 
  }, 
 
  provide: { 
    grid: [PageEditToolbar], 
  }, 
}; 
</script> 
 
Child Component: 
 
<template> 
  <button v-on:click="fun($event)">buttton</button> 
</template> 
 
<script> 
export default { 
  data() { 
    return { 
      name: "ChildComponent", 
    }; 
  }, 
  methods: { 
    fun: function (args) { 
// here we are emitting the click event 
      this.$eventHub.$emit("communicate", args); 
    }, 
  }, 
}; 
</script> 
 

For your reference we have prepared the sample with this code and you can find that sample from the below link, 

 
General link for Vue Event Bus concept: https://alligator.io/vuejs/global-event-bus/ 

Please let us know, if you need further assistance. 

Regards, 
Manivel 



TM Tom McNeer September 29, 2020 07:05 PM UTC

Hi,

Thanks very much for your help. I have implemented your suggestion regarding a global eventbus, and when using a button click to fire the event, the getRowDetails() function in your example works perfectly.

However, I now have a custom template which contains an ejs-combobox. The change event then has an event target of the list item chosen, and getRowDetails() errors because the list item is the target. I'm guessing I need to follow the target upward to some parent element, and use that to get the rowObj described in getRowDetails(). But so far I haven't been able to find the right element.

The code in the template is:

<div>
<span v-else>
<ejs-combobox
ref="statusChoice"
v-model="selectedStatusOption"
:dataSource="statusChoices"
@change="setTreatmentStatus"
style="font-size: 12px;"
></ejs-combobox>
</span>
</div>

As mentioned, the event.target here will be the list item chosen, which won't work in the example getRowDetails().

If you could tell me how to find the right element to use in determining the row data, it would be greatly appreciated.


BS Balaji Sekar Syncfusion Team September 30, 2020 02:44 PM UTC

Hi Tom, 
 
Based on your requirement we have bound the EJ2 ComboBox component instead of button in the Grid’s column using column.template feature. Using change event of ComboBox component we have emitted the event arguments to App.Vue component to get the arguments details in the getRowDetails method. 
 
We have found the current row details using combobox component’s element instead of target in the getRowObjectFromUID method of Grid. 
 
Please refer the below code example and sample for more information. 
 
[App.Vue] 
getRowDetails: function (eve) { 
      let rowObj = this.$refs.grid.ej2Instances.getRowObjectFromUID( 
        closest(eve.element, ".e-row").getAttribute("data-uid") 
      ); 
      let data = rowObj.data; 
      alert(JSON.stringify(data)); 
    }, 
 
[Child.Vue] 
<template> 
  <div> 
    <div id="content" style="margin: 0 auto; width:250px; padding-top: 30px"> 
      <ejs-combobox id="games" v-on:change="fun($event)" :dataSource="sportsData"></ejs-combobox> 
    </div> 
  </div> 
</template> 
 
<script> 
import Vue from "vue"; 
import { ComboBoxPlugin } from "@syncfusion/ej2-vue-dropdowns"; 
import { gridData } from "./data"; 
Vue.use(ComboBoxPlugin); 
export default { 
  data() { 
    return { 
      name: "ChildComponent", 
      sportsData: ["VINET", "TOMSP", "HANAR"] 
    }; 
  }, 
  methods: { 
    fun: function(args) {       
      this.$eventHub.$emit("communicate", args); 
    } 
  } 
}; 
</script> 
 
 
Please get back to us, if you need further assistance. 
 
Regards, 
Balaji Sekar 



TM Tom McNeer September 30, 2020 04:44 PM UTC

Thanks very much for your help. I think you can close this ticket.


BS Balaji Sekar Syncfusion Team October 1, 2020 04:46 PM UTC

Hi Tom, 
 
We are glad that your issue has been fixed. 
 
Please get back to us if you require further other assistance from us. 
 
Regards, 
Balaji Sekar 


Loader.
Up arrow icon