Router-link in Grid column

Hi,

Is it possible to add a router-link inside a column, and if it is, can you provide me with an example?

9 Replies

VA Venkatesh Ayothi Raman Syncfusion Team August 9, 2018 11:53 AM UTC

Hi Lajos, 
 
Thanks for using Syncfusion products. 
 
We can achieve this ‘Router link in Grid column’ using column template feature in Grid. In this feature, we can display the custom element instead of field value. Please refer to the following code example, online demo and Help documentation for more information, 
 
Code example: 
[grid] 
<ejs-grid :dataSource="data" height=350> 
            <e-columns> 
                <e-column headerText=template column' width='150' textAlign='Center' :template='cTemplate'></e-column> 
. .  . 
            </e-columns> 
        </ejs-grid> 
 
export default Vue.extend({ 
  data: () => { 
    return { 
      data: employeeData, 
      cTemplate: function () { 
          return { template : columntempVue} 
      } 
    }; 
  } 
}); 
 
[column template view] 
 
<template> 
  <div class="link"> 
 //here you can give router link 
<router-link :to="{ path: '/abc'}" replace></router-link> 
  </div> 
</template> 
 
 
 
 
 
Please let us know if you have any further assistance on this. 
 
 
Regards, 
Venkatesh Ayothiraman. 



SA Salut June 4, 2019 09:48 AM UTC

Hi,

I tried to implement your solution but I've the following error:

TypeError: "router is undefined"
    render webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:424
    VueJS 18
    node_modules syncfusion/ej2-vue-base/src/template.js:23
    node_modules syncfusion/ej2-base/src/template-engine.js:25
    node_modules syncfusion/ej2-grids/src/grid/renderer/cell-renderer.js:48
    node_modules syncfusion/ej2-grids/src/grid/renderer/cell-renderer.js:132
    node_modules syncfusion/ej2-grids/src/grid/renderer/cell-renderer.js:87
    node_modules syncfusion/ej2-grids/src/grid/renderer/row-renderer.js:89
    node_modules syncfusion/ej2-grids/src/grid/renderer/row-renderer.js:121
    node_modules syncfusion/ej2-grids/src/grid/renderer/row-renderer.js:34
    node_modules syncfusion/ej2-grids/src/grid/renderer/content-renderer.js:239
    node_modules syncfusion/ej2-grids/src/grid/renderer/render.js:326
    node_modules syncfusion/ej2-grids/src/grid/renderer/render.js:158
    run webpack-internal:///./node_modules/core-js/modules/es6.promise.js:75
    notify webpack-internal:///./node_modules/core-js/modules/es6.promise.js:92
    flush webpack-internal:///./node_modules/core-js/modules/_microtask.js:18
vue.runtime.esm.js:1888

The grid is properly displayed but any component I use inside the template are not rendered!

Here is my component:
<template>
<div class="d-flex justify-content-center">
<router-link to="/somewhere">
Hi
</router-link>

</div>
</template>

<script>
export default {
name: 'componentActions
}
</script>
And the grid component:
<template>
<div>
<ejs-grid :dataSource="data">
<e-columns>
<e-column
headerText="Actions"
textAlign="center"
class="text-center"
:template="actionTemplate"
>
</e-column>
</e-columns>
</ejs-grid>
</div>
</template>

<script>
import ComponentActions from '@/components/ComponentActions'

export default {
name: 'rootComponent',
data() {
return {
actionTemplate: () => {
return {
template: ComponentActions
}
},
...
}
}
}
</script>

<style lang="scss" scoped></style>
Thanks in advance for your help.



TS Thavasianand Sankaranarayanan Syncfusion Team June 11, 2019 05:09 PM UTC

Hi Lajos, 
 
We are working on your query with your mentioned requirement and we will update the further detail by 13th June, 2019. 
 
Until then we appreciate your patience.  
 
Regards, 
Thavasianand S. 



JA Jesus Arockia Sankaran S Syncfusion Team June 17, 2019 10:42 AM UTC

Hi Lajos, 

Sorry for the inconvenience. 

We have checked your reported issue and we would like to let you know that we have rendered the template as a separate Vue component in our EJ2, so the configured router in the Vue Application will not be accessible inside the template which is the default behavior of Vue. The router-link inside the Vue Component Template needs to be configured for proper rendering. For further reference regarding this issue please refer the below link. 
  
 
Please get back to us if you need further details on this. 
 
Regards, 
Jesus Arockia Sankaran S 



OV Ondrej Valenta replied to Jesus Arockia Sankaran S September 16, 2019 11:23 AM UTC

Hi Lajos, 

Sorry for the inconvenience. 

We have checked your reported issue and we would like to let you know that we have rendered the template as a separate Vue component in our EJ2, so the configured router in the Vue Application will not be accessible inside the template which is the default behavior of Vue. The router-link inside the Vue Component Template needs to be configured for proper rendering. For further reference regarding this issue please refer the below link. 
  
 
Please get back to us if you need further details on this. 
 
Regards, 
Jesus Arockia Sankaran S 


Hello,
could you elaborate a little bit more about that. We've tried everything we know and we cannot make this work and since this is quite a common use case there must be solution to this.

Your explanation "we have rendered the template as a separate Vue component in our EJ2, so the configured router in the Vue Application will not be accessible inside the template which is the default behavior of Vue. The router-link inside the Vue Component Template needs to be configured for proper rendering." is understandable, the mitigation steps are unfortunatelly not. 

If we have a component DownloadIcon.vue (all done with vue-cli 3)
<template>
  <div>
    <router-link to="/foo">
      FOOO
    router-link>
  div>
template>


and then a normal page that uses your grid

<template>
  <div>
    <download-icon>download-icon>
     This /foo link will be rendered just fine

    <ejs-grid
      :pageSettings="pageSettings"
      :contextMenuItems="contextOptions"
      :dataSource="documents"
      :contextMenuClick="onContextItemClick"
      :allowPaging="true"
      :allowSorting="true"
    >
      <e-columns>
        <e-column headerText="Download" :template="cTemplate">e-column>
This / foo linke want be displayed
        <e-column field="Title" headerText="Title">e-column>
      e-columns>
    ejs-grid>
  div>
template>

with
import DownloadIcon from "./icons/DownloadIcon.vue";

export default {
data() {
    return {
      cTemplate: function() {
        return { template: DownloadIcon };
      },
      documents: [
        {
          Code: "1N34WEP",
          Title: "Nadpis",
          FileName: "Sample.txt",
          Scope: "Banery",
          Modified: "2019-04-06",
          ModifiedBy: "Karel Hodoma",
          Created: "2018-01-02",
          CreatedBy: "Petra Zavřelová"
        },
        {
          Code: "2Q91AUB",
          Title: "Dokument 2",
          FileName: "Document.txt",
          Scope: "Produkce",
          Modified: "2019-11-26",
          ModifiedBy: "Zuzana Dobrotiva",
          Created: "2015-03-30",
          CreatedBy: "System"
        }
      ],
}

This simply does not work. Is there something I'm missing in your answer? Should we somehow inject router to Vue template of DownloadIcon.

Just to clarify we can display text, icons whatever in cTemplate, that works just fine, but we cannot use router-link. We have also tested global registration with Vue.component("download-icon"DownloadIcon.default || DownloadIcon); ,but it has not effect, in fact we don't know how to say to your grid to recognize this component.

Your example does not work (404 in dev console) so we cannot test that. 



OV Ondrej Valenta September 16, 2019 11:01 PM UTC

So for everyone interested it works like this.

Each component rendered as a custom template is it's own Vue instance therefor you cannot access anything router assigned to the main Vue instance. Our solution was to export const ourRouter = router; from main.js and then import it to a component where we have the data grid and call push method on this ourRouter in a method registered in the template. 

DownloadIcon.vue
<template>
  <div>
    <div class="empimg">
      <button @click="redirectToFoo">XXX</button>
    </div>
  </div>
</template>

<script>
import { ourRouter } from "../main";

export default {
  methods: {
    redirectToFoo() {
      console.log(ourRouter);

      ourRouter.push("/foo");
    }
  }
};
</script>


and in app.vue

export default {
  name: "app",
  components: {
    HelloWorld,
    Grid
  },
  data() {
    return {
      empTemplate: function() {
        return {
          template: DownloadIcon
        };
      },

in main.js

import VueRouter from 'vue-router'

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: HelloWorld
    }
  ]
})

Vue.use(GridPlugin);

Vue.config.productionTip = false

new Vue({
  router: router,
  render: h => h(App),
}).$mount('#app')

export const ourRouter = router;


It's not perfect but it's usable altough since the template is a separated Vue instance we cannot use any of our normal components. I guess there is some other solution to this.







JA Jesus Arockia Sankaran S Syncfusion Team September 17, 2019 01:28 PM UTC

Hi Ondrej,  

Template for our components are developed as separate Vue component so we cannot access the router link of the Syncfusion EJ2 component inside its own template. Yes, defining the router commonly as mentioned is the best the way to over come this problem.   

Regards,  
Jesus Arockia Sankaran S 



OV Olaf van der Meer May 1, 2020 12:55 PM UTC

Hi,

You could also use
this.$router.push("/foof");
https://router.vuejs.org/guide/essentials/navigation.html


KS Kumaresan Subramani Syncfusion Team May 5, 2020 10:42 AM UTC

Hi Olaf van der Meer, 

Thanks for your suggestion. 

Please let us know if you have any other concern. 

Regards, 
Kumaresan S 


Loader.
Up arrow icon