Setting up row components for element-ui table - vue.js

just started using Vue and Element UI libraray but got stuck with their table component: https://element.eleme.io/#/en-US/component/table
I'd like to have a component for each table row to handle all logic related to that row (actions, click, etc.) in this component but checking their documentation looks like the components are column-based. What am I missing?

Let me show you how to use the basic el-table, such as processing the data of a row
var Main = {
data() {
return {
tableData: [{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}]
}
},
methods: {
handleEdit(index, row) {
console.log(index, row);
},
handleDelete(index, row) {
// Here you can access the row data (objects in the object array) to be deleted
console.log(index, row);
this.$confirm('This will permanently delete the record. Continue?', 'Warning', {
confirmButtonText: 'OK',
cancelButtonText: 'Cancel',
type: 'warning'
}).then(() => {
this.tableData.splice(index, 1);
this.$message({
type: 'success',
message: 'Delete completed'
});
}).catch(() => {
this.$message({
type: 'info',
message: 'Delete canceled'
});
});
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
#import url("//unpkg.com/element-ui#2.12.0/lib/theme-chalk/index.css");
<script src="//unpkg.com/vue/dist/vue.min.js"></script>
<script src="//unpkg.com/element-ui#2.12.0/lib/index.js"></script>
<div id="app">
<template>
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
label="Date"
width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>
<el-table-column label="Name" width="180">
<template slot-scope="scope">
<el-tag size="medium">{{ scope.row.name }}</el-tag>
</template>
</el-table-column>
<el-table-column label="Operations">
<template slot-scope="scope">
<el-button
size="mini"
#click="handleEdit(scope.$index, scope.row)">Edit</el-button>
<el-button
size="mini"
type="danger"
#click="handleDelete(scope.$index, scope.row)">Delete</el-button>
</template>
</el-table-column>
</el-table>
</template>
</div>

Based on Sugars' answer you can toggle an input to allow edits throughout the columns on each row. I've made a simple demo based on his answer.
var Main = {
data() {
return {
tableData: [{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
editable: false
}, {
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
editable: false
}, {
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
editable: false
}, {
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
editable: false
}]
}
},
methods: {
handleEdit(index, row) {
console.log(index, row);
row.editable = !row.editable;
},
handleDelete(index, row) {
// Here you can access the row data (objects in the object array) to be deleted
console.log(index, row);
this.$confirm('This will permanently delete the record. Continue?', 'Warning', {
confirmButtonText: 'OK',
cancelButtonText: 'Cancel',
type: 'warning'
}).then(() => {
this.tableData.splice(index, 1);
this.$message({
type: 'success',
message: 'Delete completed'
});
}).catch(() => {
this.$message({
type: 'info',
message: 'Delete canceled'
});
});
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
#import url("//unpkg.com/element-ui#2.12.0/lib/theme-chalk/index.css");
<script src="//unpkg.com/vue/dist/vue.min.js"></script>
<script src="//unpkg.com/element-ui#2.12.0/lib/index.js"></script>
<div id="app">
<template>
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
label="Date"
width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px" v-if="!scope.row.editable">{{ scope.row.date }}</span>
<el-date-picker v-model="scope.row.date" v-if="scope.row.editable"></el-date-picker>
</template>
</el-table-column>
<el-table-column label="Name" width="180">
<template slot-scope="scope">
<el-tag size="medium" v-if="!scope.row.editable">{{ scope.row.name }}</el-tag>
<el-input v-model="scope.row.name" v-if="scope.row.editable"></el-input>
</template>
</el-table-column>
<el-table-column label="Operations">
<template slot-scope="scope">
<el-button
size="mini"
#click="handleEdit(scope.$index, scope.row)">Edit</el-button>
<el-button
size="mini"
type="danger"
#click="handleDelete(scope.$index, scope.row)">Delete</el-button>
</template>
</el-table-column>
</el-table>
</template>
</div>

Related

html2pdf how to prevent table column from breaking midway

I'm using vue-html2pdf to generate a pdf report. To avoid row breaking pagebreak: { mode: ["avoid-all", "css", "legacy"] } is used. However, a few of the columns of the generated report are growing vertically, and also making the rows to break in the report. How can this issue be fixed with auto pagebreak configuration?
Template
<template>
<div>
<VueHtml2pdf
:show-layout="false"
:float-layout="true"
:enable-download="true"
:preview-modal="true"
:paginate-elements-by-height="1300"
filename="ABCD-Report"
:pdf-quality="1"
pdf-format="a2"
pdf-orientation="landscape"
:html-to-pdf-options="htmlToPdfOptions"
pdf-content-width="2200px"
ref="html2Pdf"
#hasDownloaded="onDownload"
#beforeDownload="beforeDownload($event)"
>
<section slot="pdf-content">
<div style="margin: 30px">
<h2>Report Data:</h2>
<br />
<el-table :data="sampleData">
<el-table-column prop="instruction" label="Instruction">
</el-table-column>
<el-table-column prop="description" label="Description">
</el-table-column>
<el-table-column prop="reason" label="Reason">
</el-table-column>
<el-table-column
prop="documentation" label="Documentation">
</el-table-column>
<el-table-column prop="work" label="Work">
</el-table-column>
</el-table>
</div>
</section>
</VueHtml2pdf>
</div>
</template>
Script
<script>
import VueHtml2pdf from "vue-html2pdf";
export default {
name: "GenerateReportPdf",
components: { VueHtml2pdf },
data() {
return {
sampleData: null,
};
},
computed: {
htmlToPdfOptions() {
return {
margin: [0, 0],
filename: "ABCD-Report.pdf",
image: { type: "jpeg", quality: 1, format: "a2" },
html2canvas: { scale: 1, letterRendering: true },
jsPDF: {
unit: "pt",
format: "a2",
orientation: "landscape",
},
pagebreak: { mode: ["avoid-all", "css", "legacy"] },
};
},
},
methods: {
//methods added here to fetch the report data
},
};
</script>

Elment Plus + Vue3 js table with dynamic table columns , input box inside the table

the actual display of the table
Got problems with data-binding under such circumstance. Input boxes from the whole row seems to be recognizede as one.
<h2>Vue3 + Element plus Dyanamic table</h2>
<el-table :data="tableData" style="width: 100%">
<el-table-column
:prop="index"
:label="item"
v-for="(item, index) in tableHeader"
:key="index"
>
<template v-slot="scope">
<el-input :name="item" v-model="scope.row.index"></el-input>
</template>
</el-table-column>
</el-table>
data() {
return {
tableHeader: {
1: "Name",
2: "Birthday",
3: "Address",
4: "Age",
5: "Tel",
},
tableData: [{
1:'',
2:'',
3:'',
4:'',
5:'',
}, {
1:'',
2:'',
3:'',
4:'',
5:'',
}]
I'm trying to load the table header(namely the number of the columns and each column's name) from back-end data. Input boxes is the main feature in this table. And i want to store the data fram input boxes into tableData and then send it back to back-end.How could i fix this?
Here is an example of a very basic Element+ Table from the Docs.
The way you are trying to bind props to index does not make sense to me.
<template>
<el-table :data="tableData" stripe style="width: 100%">
<el-table-column prop="date" label="Date" width="180" />
<el-table-column prop="name" label="Name" width="180" />
<el-table-column prop="address" label="Address" />
</el-table>
</template>
<script lang="ts" setup>
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
</script>

How to add grouping to vuetable-2?

I want to add a grouping to a vuetable based on OrderingHeaderId dynamically. I used vuetable-2 library to create this table. Please advise me on how to add the grouping concept to this kind of table.
data: function () {
return {
isLoading: false,
searchItems: null,
recordCount: 0,
issueMealIssuedCount: 0,
apiUrl: this.$http.defaults.baseURL + "/api/issue-meal/search",
fields: [
{
name: VuetableFieldCheckbox,
title: "checkbox",
width: "40px",
titleClass: "left aligned",
dataClass: "left aligned",
},
{
name: "OrderingHeaderId",
title: "Order Id",
},
{
name: "TotIssued",
title: "Tot Issued Amont",
},
{
name: "ItemName",
title: "Item Name",
},
{
name: "CostPrice",
title: "Selling Price",
},
{
name: "Quantity",
title: "Quantity",
},
{
name: "Status",
title: "Status",
width: "15%",
},
],
sortOrder: [
{
field: "ItemName",
direction: "asc",
},
],
};
},
<vuetable
:css="css.table"
ref="vuetable"
:api-url="apiUrl"
:load-on-start="false"
http-method="post"
:fields="fields"
data-path="data"
pagination-path="summary"
#vuetable:pagination-data="onPaginationData"
:append-params="moreParams"
#vuetable:loading="onLoading"
#vuetable:loaded="onLoaded"
#vuetable:checkbox-toggled="toggleCheckbox($event)"
#vuetable:checkbox-toggled-all="toggleCheckbox($event)"
:sort-order="sortOrder"
:per-page="perPage"
track-by="TrackId"
>
<template slot="OrderingHeaderId" slot-scope="props">
<div class="col-sm-12">
<span v-html="props.rowData.OrderingHeaderId"></span>
</div>
</template>
<template slot="TotIssued" slot-scope="props">
<div class="col-sm-12">
<span v-html="props.rowData.TotIssued"></span>
</div>
</template>
<template slot="ItemName" slot-scope="props">
<div class="col-sm-12">
<span v-html="props.rowData.ItemName"></span>
</div>
</template>
<template slot="CostPrice" slot-scope="props">
<div class="col-sm-12">
<span v-html="props.rowData.UnitPrice"></span>
</div>
</template>
<template slot="Quantity" slot-scope="props">
<div class="col-sm-12">
<span v-html="props.rowData.Quantity"></span>
</div>
</template>
<template slot="Status" slot-scope="props">
<div class="text-center">
<hcx-switch
v-model="props.rowData.OrderType"
:readonly="props.rowData.IsStatusSaved"
:id="props.rowIndex.toString()"
true-value="1"
false-value="2"
true-text="Issued"
false-text="Cancelled"
/>
</div>
</template>
</vuetable>

How to change style in specific row in Element UI Table

I'm using Element UI for my web app.
In my app, there is a table component, that is made by el-table component provided by Element UI.
And I would like to change style for the only specific row.
Firstly, please take a look at the screenshot and my code, later, I will explain what I would like to do specifically with them.
These are the screenshot of table in my app and my code.
<template>
<el-table
:data="tableData"
height="250"
style="width: 100%">
<el-table-column
prop="date"
label="Date"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="Name"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="Address">
</el-table-column>
</el-table>
</template>
<script>
export default {
data() {
return {
tableData: [{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-08',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-06',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}, {
date: '2016-05-07',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}],
}
}
}
</script>
I would like to change background color blue for the row that's Data is 2016-05-03 and 2016-05-04 in the case above.
You should have a look at this https://element.eleme.io/#/en-US/component/table#table-with-status. based on the property row-class-name you can apply some logic to add an class to the row.
<el-table
:data="tableData"
style="width: 100%"
:row-class-name="tableRowClassName">
JS
methods: {
tableRowClassName({row, rowIndex}) {
if (row.date >= new Date()) {
return 'warning-row';
} else if (rowIndex === 3) {
return 'success-row';
}
return '';
}
},
Of course you've to customize this to your needs
Add this code on the component stylesheet
.el-table tr:nth-child(odd) {
background-color: #845353;
}
Additionally +
If you are using the new version of Element-UI and row-style instead of header-row-class-name, you must not use like return: 'background: red'. You have to return Object.
ex: return: {'background': 'red'}

Vuetify, v-for checkbox with search field. Strange behavior on the checkbox

I'm making a list of person to select with a search bar to find the person name. I'm using computed and filter to search the list. But there's strange behavior on my checklist. I don't know what happen. Please check the codepen link above. Try searching then delete the search.
https://codepen.io/rahmatfajar15/pen/OqPqRy?editors=1010
template:
<v-layout column fill-height>
<v-flex>
<v-text-field
v-model="pattern"
box
hide-details
label="Cari Peserta..."
prepend-inner-icon="search"
clear-icon="close"
clearable
/>
</v-flex>
<v-layout column>
<div
v-for="item in filteredPeserta"
>
<v-layout row class="text-xs-left">
<div class="xs2 justify-center align-center">
<v-checkbox
height="16"
v-model="tempPeserta"
:value="item.id"
/>
</div>
<v-layout xs10 column justify-center>
<pre class="body-2">{{ item.name }}</pre>
</v-layout>
</v-layout>
</div>
</v-layout>
</v-layout>
script:
new Vue({
el: '#app',
data: () => ({
pattern: '',
tempPeserta: [],
listPeserta: [
{
id: '1',
name: 'Agung'
},
{
id: '2',
name: 'Bucin'
},
{
id: '3',
name: 'Chandra'
},
{
id: '4',
name: 'Dedek'
},
{
id: '5',
name: 'Enok'
},
{
id: '6',
name: 'Fajar'
},
{
id: '7',
name: 'Galih'
},
{
id: '8',
name: 'Hayo'
},
{
id: '9',
name: 'Ilsa'
},
]
}),
computed: {
filteredPeserta () {
return this.listPeserta.filter(item => {
return item.name.toLowerCase().indexOf(this.pattern.toLowerCase()) > -1
})
}
}
})
You need to add key when using v-for because Vue will reuse list component (document)
<div
v-for="item in filteredPeserta"
:key="item.id"
>
....
</div>