Column template in Vue Treegrid not working

Hi, 

I've created a component in my Vue project where I've implemented a TreeGrid. I added an extra "Action" column using a template to display a button.

I initially tried the method described in the documentation, but it didn't seem to work—I suspect it might not be compatible with Vue 3 Composition API.

As an alternative, I tried returning a string containing HTML and Vue-specific directives (e.g., v-on:click()), but this isn't compiled by Vue, and consequently, it doesn't work but the buttons are displayed good : 

<template>
  <div>
    <ejs-treegrid class="tableau-syncfusion-itl" :dataSource='storeDp.dp.listApportCaveGroupByProduitTreeGrid'
      :treeColumnIndex='0' childMapping='listApportCaveByProduit' :allowTextWrap="true">
      <e-columns>
        <e-column field='nomProduit' headerText='Produit' textAlign='Left' width=20></e-column>
        <e-column field='mentionValorisante' headerText='Mention Valorisante' textAlign='Center' width=20></e-column>
        <e-column field='superficieRecolteTotal' headerText='Superficie' textAlign='Center' width=20></e-column>
        <e-column field='volumeApportRaisinTotal' headerText='Apport raisin' textAlign='Center' width=20></e-column>
        <e-column field='volumeIssuRaisinTotal' headerText='Issue raisin' textAlign='Center' width=20></e-column>
        <e-column field='volumeApportMoutTotal' headerText='Apport moût' textAlign='Center' width=20></e-column>
        <e-column field='volumeIssuMoutTotal' headerText='Issue moût' textAlign='Center' width=20></e-column>
        <e-column field='' headerText='Action(s)' :template='actionTemplate' textAlign='Center' width=20></e-column>
      </e-columns>
    </ejs-treegrid>
  </div>
</template>

<script setup lang="ts">
import type { ApportCaveGroupByProduitTreeGridDto } from '@/models/DeclarationProduction/DeclarationProductionDto';
import { useDeclarationProductionStore } from '@/stores/DeclarationProductionStore';
import { TreeGridComponent as EjsTreegrid, ColumnsDirective as EColumns, ColumnDirective as EColumn } from '@syncfusion/ej2-vue-treegrid';

const storeDp = useDeclarationProductionStore();

// Ici, on définit réellement "actionTemplate".
// Syncfusion invoque cette fonction pour chaque cellule "Action(s)".
// "props" contient { data, column, row } etc.
function actionTemplate(props: ApportCaveGroupByProduitTreeGridDto) {
  // Si c’est un parent => a un tableau d’enfants
  const hasChildren = props.listApportCaveByProduit?.length > 0;

  if (hasChildren) {
    // Template pour une ligne parent
    return `
      <div class="row d-flex justify-content-center">
        <button type="button"
          v-on:click="addLigneDp(${props.idProduit})"
          class="btn button-cta add-button col-md-5"
          title="Ajouter un apport fournisseur"
        >
          <i class="fa-solid fa-plus fa-lg"></i>
        </button>
      </div>
    `;
  } else {
    // Template pour une ligne enfant
    return `
      <div class="row d-flex justify-content-center">
        <button type="button"
          @click="editLigneDp(${props.idLigneDeclarationProduction})"
          class="btn button-cta valide-button col-md-5"
          title="Modifier l'apport fournisseur"
        >
          <i class="fa-solid fa-pen-to-square"></i>
        </button>
      </div>
    `;
  }
}
</script>


I also attempted using Vnodes directly, but in this case, nothing is displayed in the template column.

import { h } from 'vue'

function actionTemplate(props: ApportCaveGroupByProduitTreeGridDto) {
  const hasChildren = props.listApportCaveByProduit?.length > 0;

  if (hasChildren) {
    // LIGNE PARENT => bouton "Ajouter"
    return h(
      'div',
      { class: 'row d-flex justify-content-center' },
      [
        h(
          'button',
          {
            type: 'button',
            class: 'btn button-cta add-button col-md-5',
            title: 'Ajouter un apport fournisseur',
            // Evénement click
            onClick: () => addLigneDp(props.idProduit)
          },
          [
            h('i', { class: 'fa-solid fa-plus fa-lg' })
          ]
        )
      ]
    )
  } else {
    // LIGNE ENFANT => bouton "Modifier"
    return h(
      'div',
      { class: 'row d-flex justify-content-center' },
      [
        h(
          'button',
          {
            type: 'button',
            class: 'btn button-cta valide-button col-md-5',
            title: 'Modifier l\'apport fournisseur',
            // Evénement click
            onClick: () => editLigneDp(props.idLigneDeclarationProduction)
          },
          [
            h('i', { class: 'fa-solid fa-pen-to-square' })
          ]
        )
      ]
    )
  }
}

function addLigneDp(idProduit: number) {
  console.log("IdProduit:", idProduit)
  // votre logique...
}

function editLigneDp(idLigne: number) {
  console.log("idLigneDeclarationProduction:", idLigne)
  // votre logique...
}


Could you tell me the best practice to achieve this properly, following Vue 3's recommended approach?

Antoine


1 Reply 1 reply marked as answer

SK Sreedhar Kumar Panarapu Sreenivasulu Panarapu Syncfusion Team March 24, 2025 01:27 PM UTC

Hi Francelink,

Thank you for your patience.

We have reviewed your query and recommend using the template tag for defining the action column in your TreeGrid. Below is a working code snippet:

    <!-- Actions Column with Correct Slot -->

        <e-column headerText="Actions" width="110" :template="'actionTemplate'"></e-column>

      </e-columns>

 

      <!-- Define Slot Template -->

      <template #actionTemplate="{ data }">

        <span>Hello {{ data.taskName }}</span>

      </template>

 
 

For more details on command column editing, refer to the official API documentation:
Command Column Editing in Vue TreeGrid

Please refer to the attached sample for your reference. To run the sample, use the following commands:

pnpm install  
pnpm run serve  

Let us know if you need further assistance.

Best regards,
Sreedhar Kumar

 

 


Attachment: vue3compositionapi_1d751943.zip

Marked as answer
Loader.
Up arrow icon