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