Pour réaliser un formulaire de saisie dans un tableau, les données sont stockées côté back end sous forme de structure tabulaire. Une fois récupérées sous forme de tableau JSON, elles sont affichées dans l'interface utilisateur.
Le principe est d'utiliser l'événement cell-click pour basculer entre l'affichage du contenu textuel et un champ de saisie, en contrôlant un indicateur booléen.
<el-table :data="tableData" border @cell-click="handleCellClick">
<el-table-column label="Élément à vérifier" align="center" prop="name" />
<el-table-column prop="result" label="Résultat">
<template slot-scope="{ row }">
<el-radio v-model="row.result"
v-for="dict in resultOptions"
:key="dict.dictValue"
:label="dict.dictValue">
{{ dict.dictLabel }}
</el-radio>
</template>
</el-table-column>
<el-table-column label="Critère" align="center" prop="checkStandard" width="350" />
<el-table-column prop="hitch" label="Défaillance">
<template slot-scope="scope">
<span v-if="!scope.row.isEditable" style="cursor:pointer">{{ scope.row.hitch }}</span>
<el-input v-if="scope.row.isEditable"
v-model="scope.row.hitch"
placeholder="Emplacement de la défaillance"
@blur="onCellBlur(scope.row, scope.column)"
style="width:70%" ref="hitchRef"></el-input>
</template>
</el-table-column>
<el-table-column prop="remark" label="Remarque">
<template slot-scope="scope">
<span v-if="!scope.row.isEditable" style="cursor:pointer">{{ scope.row.remark }}</span>
<el-input v-if="scope.row.isEditable"
v-model="scope.row.remark"
placeholder="Saisir une remarque"
@blur="onCellBlur(scope.row, scope.column)"
style="width:70%" ref="remarkRef"></el-input>
</template>
</el-table-column>
</el-table>
Script correspondant :
data() {
return {
tableData: [],
resultOptions: null,
submitData: {},
inspectId: ''
};
},
created() {
this.inspectId = this.$route.params?.inspectId;
this.fetchTableData(this.inspectId);
this.getDicts("sys_check_result").then(response => {
this.resultOptions = response.data;
});
},
methods: {
fetchTableData(inspectId) {
this.loading = true;
listInspectItem(inspectId).then(response => {
this.tableData = response.data;
this.tableData.forEach(item => {
this.$set(item, 'isEditable', false);
});
this.loading = false;
});
},
handleCellClick(row, column) {
if (["remark", "result", "hitch"].includes(column.property)) {
this.$set(row, 'isEditable', true);
}
this.tableData = [...this.tableData]; // Forcer la mise à jour du rendu
this.$nextTick(() => {
if (column.property === "remark" && this.$refs.remarkRef) {
this.$refs.remarkRef.focus();
} else if (this.$refs.hitchRef) {
this.$refs.hitchRef.focus();
}
});
},
onCellBlur(row, column) {
this.$set(row, 'isEditable', false);
},
submitForm(row) {
this.loading = true;
const payload = {
inspectId: this.inspectId,
ext1: JSON.stringify(this.tableData)
};
updateInspect(payload).then(response => {
if (response.code === 200) {
this.msgSuccess("Modification réussie");
this.loading = false;
this.fetchTableData(this.inspectId);
} else {
this.msgError(response.msg);
}
});
}
}
Variante 1 : Utilisation de cell-dblclick et d'une colonne d'index
Template :
<el-table
:data="tableData"
border
@cell-dblclick="onDoubleClick"
highlight-current-row
:cell-style="defineRowStyle"
style="width: 100%">
<el-table-column type="index" label="#" width="50"></el-table-column>
<el-table-column prop="username" label="Responsable" width="180">
<template v-slot="{ row, column, $index }">
<el-input
:ref="$index"
v-show="isCurrentCell(row, column, $index)"
v-model="row.username"
@blur="handleBlur"
placeholder="Saisir le nom">
</el-input>
<span v-show="!isCurrentCell(row, column, $index)">{{ row.username }}</span>
</template>
</el-table-column>
</el-table>
Script :
methods: {
onDoubleClick(row, column, cell, event) {
if (column.property !== 'username') return;
this.selectedRowIndex = row.rowIndex;
this.selectedColProperty = column.property;
},
defineRowStyle(obj) {
Object.defineProperty(obj.row, 'rowIndex', {
value: obj.rowIndex,
writable: true,
enumerable: false
});
},
isCurrentCell(row, col, index) {
return row.rowIndex === this.selectedRowIndex && col.property === this.selectedColProperty;
}
}
Variante 2 : Gestion de l'état d'édition par propriété dynamique
Template :
<el-table
:data="tableData"
border
highlight-current-row
style="width: 100%">
<el-table-column type="index" label="#" width="50"></el-table-column>
<el-table-column prop="username" label="Responsable" width="180">
<template v-slot="{ row, column, $index }">
<el-input
:ref="$index"
v-show="row[`${column.property}Editable`]"
v-model="row.username"
placeholder="Saisir le nom">
</el-input>
<span
@dblclick="activateEdit($index, column)"
v-show="!row[`${column.property}Editable`]">
{{ row.username }}
</span>
</template>
</el-table-column>
</el-table>
Script :
data() {
return {
tableData: [{
username: 'lily',
usernameEditable: false
}, {
username: 'tony',
usernameEditable: false
}]
};
},
methods: {
activateEdit(rowIndex, col) {
this.$set(this.tableData[rowIndex], `${col.property}Editable`, true);
}
}