Vue Recommendation for Storing Variable Inside Templated Looping Structure? - vue.js

Given the following code
// Assuming records is an array of objects
// Record is of the form {"fname": "John", "lname": "Smith", "dob": 1499994497871}
// Field mapper is
[
{
"name": "fname",
"label": "First Name",
"render": function(val){ return val}
},
{
"name": "lname",
"label": "Last Name",
"render": function(val){ return val}
},
{
"name": "dob",
"label": "Date of Birth",
"render": function(val){ return new Date(val).toDateString()}
}
]
// Assume findField returns the mapper instance for a given record in the records array
<div v-for="record in records">
<div>
<table class="table">
<tbody>
<tr v-for="(value, key) in record">
<th v-if="findField(key)">{{ findField(key).label }}</th>
<td v-if="findField(key)">{{ findField(key).render(value) }}</td>
</tr>
</tbody>
</table>
</div>
</div>
I'm making four calls to findField().
What's the Vue recommendation to storing variables inside looping structure?
In other words, after the first tr, something like:
let localInstance = findField(key)

One way is to use a component.
Vue.component("row", {
props:["map", "value"],
template:`
<tr>
<th v-if="map">{{ map.label }}</th>
<td v-if="map">{{ map.render(value) }}</td>
</tr>
`
})
And modify your template to use it.
<tr is="row" v-for="(value, key) in record"
:map="findField(key)"
:value="value">
</tr>
console.clear()
const fieldMap = [{
"name": "fname",
"label": "First Name",
"render": function(val) {
return val
}
},
{
"name": "lname",
"label": "Last Name",
"render": function(val) {
return val
}
},
{
"name": "dob",
"label": "Date of Birth",
"render": function(val) {
return new Date(val).toDateString()
}
}
]
const records = [{
"fname": "John",
"lname": "Smith",
"dob": 1499994497871
},
{
"fname": "John",
"lname": "Smith",
"dob": 1499994497871
},
{
"fname": "John",
"lname": "Smith",
"dob": 1499994497871
}
]
Vue.component("row", {
props: ["map", "value"],
template: `
<tr>
<th v-if="map">{{ map.label }}</th>
<td v-if="map">{{ map.render(value) }}</td>
</tr>
`
})
new Vue({
el: "#app",
data: {
records
},
methods: {
findField(key) {
return fieldMap.find(m => m.name === key)
}
},
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<div v-for="record in records">
<div>
<table class="table">
<tbody>
<tr is="row" v-for="(value, key) in record" :map="findField(key)" :value="value">
</tr>
</tbody>
</table>
</div>
</div>
</div>

Related

How Can I get a specific array id from a v-for loop input and pass it into a data store?

Here is my code
<template>
<div class="w-full bg-white mt-13">
<div class="flex flex-col mx-12 mt-8">
<div>
<table class="w-full h-auto my-12 border border-collapse table-auto">
<tr class="border">
<th v-for="i in columns" :key="i.name" class="border">
{{ i.title }}
</th>
</tr>
<tr v-for="p in getParticipants" :key="p.id">
<td class="border"></td>
<td class="border">{{ p.fullName }}</td>
<td class="border">{{ p.phone }}</td>
<td class="border">{{ p.participantId }}</td>
<td
v-for="(btn, index) in buttonCheckAtt"
:key="index"
class="border select-attendance"
>
<div>
<button
:unique-key="true"
class="w-full h-16 text-transparent"
:class="[
btn.className,
{ selected: selectedIndex === index },
]"
#click="selectedIndex = index"
>
{{ btn.btnText }}
</button>
</div>
</td>
<td class="w-16 border">
<input
ref="p.participantId"
#change="updateRemarks()"
v-model="note"
/>
</td>
</tr>
<tr></tr>
</table>
</div>
</div>
</div>
</template>
<script>
import Button from "#/components/form/Button.vue";
import { mapGetters } from "vuex";
const columns = [
{
title: "#",
},
{
title: "Name",
},
{
title: "Phone Number",
},
{
title: "ID",
},
{
title: "P",
},
{
title: "A",
},
{
title: "AP",
},
{
title: "L",
},
{
title: "Remarks",
},
];
const data = [];
export default {
components: { Button },
data() {
return {
note: null,
participantId: "abc-1",
};
},
methods: {
updateRemarks() {
let data = {
participants: [
{
participantId: this.participantId,
attendance: {
status: this.status,
note: this.note,
markBy: "organizer-id",
markMethod: "manual",
},
},
],
};
this.$store.dispatch(
"$_studyGroup/addRemarks",
{ participantData: data },
{ root: true }
);
},
},
computed: {
...mapGetters({
getParticipants: "$_studyGroup/getParticipants",
}),
},
mounted() {
this.$store.dispatch("$_studyGroup/getParticipants", {}, { root: true });
},
};
</script>
I want to use this input to this input to make patch request into my getParticipants api however it requires me to pass the participantId into the participants data in order to make patch request and I have no idea how to retrieve that participantId from the v-for loop
<input
ref="p.participantId"
#change="updateRemarks()"
v-model="note"
/>
and down below is what my getParticipants api looks like I want to pass the abc-1 and abc-2 id into the attendance in order to make patch request
getParticipants = [
{
"status": "join",
"createdAt": "2022-09-20T07:30:06.753Z",
"calendarId": "6553c8ea-0139-4802-b5d6-127e44b95412",
"email": "john#gmail.com",
"fullName": "John",
"participantId": "abc-1",
"attendance": {
"participantId" : {{participantId}},
"markBy": "organizer-id",
"markMethod": "manual",
"note": "Because of traffic jam",
"status": "Present"
},
{
"status": "join",
"createdAt": "2022-09-20T07:30:06.753Z",
"calendarId": "6553c8ea-0139-4802-b5d6-127e44b95412",
"email": "chris#gmail.com",
"fullName": "Chris",
"participantId": "abc-2",
"attendance": {
"participantId" : {{participantId}},
"markBy": "organizer-id",
"markMethod": "manual",
"note": "Because of traffic jam",
"status": "Late"
},]

How to map specializations array with JSON Vue/vuex

Hello guys,
// I have one problem with map in Vue.js, how can i map array specializations ? How to display a whole array in 1 div. I would like to make a filter later.
Below it's my JSON file
My JSON file
{
"workers": [
{
"id":1,
"name":"Karolina Water",
"email":"Karolina.water#gmail.com",
"specializations": [
{
"code": "net",
"name": ".NET"
},
{
"code": "react",
"name": "React JS"
}
]
}, {
"id":2,
"name":"Marcelina Wart",
"email":"Marcelina.wart#gmail.com",
"specializations": [
{
"code": "net",
"name": ".NET"
}
]
},
]
}
Below it's my component,
<tr v-for="worker in workers" :key="worker.id">
<th scope="row">{{ worker.id }}</th> //
<td>{{ worker.name }}</td> //
<td>{{worker.specializations[0].name}} </td> //- but i have only 1 value from the array.
<td>go to projects ➡</td>
</tr>
many thanks for your help !
Make a nested v-for.
See it here in action: Vue SFC Playground
<template>
<table border>
<tr v-for="worker in workers" :key="worker.id">
<th scope="row">{{ worker.id }}</th>
<td>{{ worker.name }}</td>
<td>
<div v-for="spec in worker.specializations">
{{spec.code}} - {{spec.name}}
</div>
</td>
</tr>
</table>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
data() {
return {
workers: [
{
id: 1,
name: "Karolina Water",
email: "Karolina.water#gmail.com",
specializations: [
{
code: "net",
name: ".NET",
},
{
code: "react",
name: "React JS",
},
],
},
{
id: 2,
name: "Marcelina Wart",
email: "Marcelina.wart#gmail.com",
specializations: [
{
code: "net",
name: ".NET",
},
],
},
],
};
},
});
</script>

How to output a vuejs nested array to a table

I want to output this JSON data to a table.
I do not know how to put the contents of "fields" into the same Tr tag.
{
"page": [
{
"type": "Type A",
"fields": [
{
"type": "Type1",
"code": "field1",
"size": {
"width": "200",
"height":"50"
}
},
{
"type": "Type2",
"code": "field2",
"size": {
"width": "250",
"height":"50"
}
}
]
},
{
"type": "Type B",
"fields": [
//....
]
}
],
"revision": "1"
}
I wrote this html
<table>
<thead>
<tr>
<th>Parent-Type</th>
<th>Child-Type</th>
<th>code</th>
<th>width</th>
<th>height</th>
</tr>
</thead>
<tbody id="my-tbody" v-cloak>
<tr v-for="(item, i) in rowData">
<td>
{{item.type}}
</td>
<td v-for="(field, j) in Object.keys(item.fields)">
{{field.code}}
</td>
</tr>
</tbody>
</table>
<scprit>
(() =>{
new Vue({
el: "#my-tbody",
data: {
rowData: []
},
created() {
let _self = this
getLayout().then(function (resp) {
_self.rowData = resp.page;
});
}
});
})();
</script>
I want to create a tr tag for each "page" ,and a td tag for each "fields".
Is it better to format in single-tiered JSON and set it in data?
Thanks.
Try something like this:
<table>
<thead>
<tr>
<th>Parent-Type</th>
<th>Child-Type</th>
<th>code</th>
<th>width</th>
<th>height</th>
</tr>
</thead>
<tbody id="my-tbody" v-cloak>
<tr v-for="item in rowData" :key="item.type">
<td>
{{item.type}}
</td>
<td v-for="field in item.fields" :key="field.code">
{{field.code}}
</td>
</tr>
</tbody>
</table>
Regards

How do I generate a table with merged rows from a nested object using vue v-for loops?

I have the following nested Javascript array which I want to generate into a table (final html shown in output) using vue v-for loops. What is the best way to go about? I've tried nested v-for loops but it turn out wrongly.
Input:
[{
"school_name": "Test School A",
"classes": [{
"class_name": "Class A",
"students": [
{ "student_name": "John", "grade" : "A"}
{ "student_name": "Andrew", "grade" : "B"}
{ "student_name": "Peter", "grade" : "C"}
]
},{
"class_name": "Class B",
"students": [
{ "student_name": "Alice", "grade" : "C"}
{ "student_name": "Ronald", "grade" : "A"}
{ "student_name": "Katherine", "grade" : "B"}
]
}]},{
"school_name": "Test School B",
"classes": [{
"class_name": "Class C",
"students": [
{ "student_name": "John", "grade" : "B"}
{ "student_name": "Ronald", "grade" : "B"}
{ "student_name": "Jacob", "grade" : "B"}
]
},{
"class_name": "Class D",
"students": [
{ "student_name": "Maia", "grade" : "C"}
{ "student_name": "Narine", "grade" : "C"}
{ "student_name": "Olivia", "grade" : "A"}
]
}]}]
Output
<table>
<tbody>
<tr>
<td rowspan="6">School A</td>
<td rowspan="3">Class A</td>
<td>John</td>
</tr>
<tr>
<td>Peter</td>
</tr>
<tr>
<td>Andrew</td>
</tr>
<tr>
<td rowspan="3">Class B</td>
<td>Alice</td>
</tr>
<tr>
<td>Ronald</td>
</tr>
<tr>
<td>Katherine</td>
</tr>
</tbody>
</table>
I couldn't make any better nor any more dynamic, but it will work just right for your need.
<template>
<div id="app">
<table border="1" style="border-collapse: collapse">
<tbody>
<template v-for="(school, currentSchool) in data">
<template v-for="(schoolClass, currentClass) in school.classes">
<tr v-for="(student, currentStudent) in schoolClass.students">
<td v-if="currentStudent+currentClass == 0" :rowspan="rowspanSchool[school.school_name]">
{{school.school_name}}
</td>
<td v-if="currentStudent == 0" :rowspan="rowspanClass[schoolClass.class_name]">{{schoolClass.class_name}}</td>
<td>{{student.student_name}}</td>
</tr>
</template>
</template>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: 'app',
computed: {
rowspanSchool() {
let schoolSpans = {};
for (let school in this.data) {
let total = 0;
for (let schoolClass in this.data[school].classes) {
for (let student in this.data[school].classes[schoolClass].students) {
total++;
}
}
schoolSpans[this.data[school].school_name] = total;
}
return schoolSpans
},
rowspanClass() {
let classSpans = {};
for (let school in this.data) {
for (let schoolClass in this.data[school].classes) {
let total = 0;
for (let student in this.data[school].classes[schoolClass].students) {
total++;
}
classSpans[this.data[school].classes[schoolClass].class_name] = total;
}
}
return classSpans
}
},
data() {
return {
data: arrayData
}
}
}
</script>

Anchor tag on Datatable column

Anchor tag on field column .
How do i add a anchor tag along with title in datatable .
Here is the code:
$(document).ready(function ()
{
debugger
$('#TableId').DataTable(
{
//"columnDefs": [
// { "width": "5%", "targets": [0] },
// {
// "className": "text-center custom-middle-align",
// "targets": [0, 1, 2, 3, 4, 5, 6]
// },
//],
'columnDefs': [{
'targets': 0,
'searchable': false,
'orderable': false,
'width': '1%',
'className': 'dt-body-center',
'render': function (data, type, full, meta) {
return '<input type="checkbox">';
}
}],
"language":
{
"processing": "<div class='overlay custom-loader-background'><i class='fa fa-cog fa-spin custom-loader-color'></i></div>"
},
"processing": true,
"serverSide": true,
"ajax":
{
"url": "/TicketTemplate/GetData",
"type": "POST",
"dataType": "JSON"
},
"columns": [
{ "data": '' },
{ "data": "CreatedDate" },
{ "data": "Title" },
//{
// //"data": "Title",
// "render": function (data, type, row, meta) {
// //return '' + Title + '';
// return '' + data + '';
// }
//},
{ "data": "Name" },
{ "data": "Email" },
{ "data": "AssignTo" },
{ "data": "Status" }
]
});
});
Here in the above code in the case of "Title" it must be an a anchor tag..
so any suggestions??
Here is the table:
<table class="table table-striped table-bordered table-hover" id="TableId">
<thead>
<tr>
<th>
<label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">
<input type="checkbox" class="group-checkable" id="chkall" data-set="#sample_2.checkboxes" onclick="Selectallcheckbox()" />
<span></span>
</label>
</th>
<th> Date Created </th>
<th> Title </th>
<th> User Name </th>
<th> User Email </th>
<th>Assigned To </th>
<th> Status </th>
</tr>
</thead>
<tbody>
#foreach (var itm in Model.TicketList)
{
<tr class="odd gradeX">
<td>
<label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">
<input type="checkbox" class="checkboxes" value="1" />
<span></span>
</label>
</td>
<td class="center"> #itm.CreatedDate.ToString("MM/dd/yyyy") </td>
<td>
#*#itm.Title*#
#itm.Title
</td>
<td> #itm.Name </td>
<td>
#itm.Email
</td>
<td> #itm.AssignTo </td>
<td>
<span class="label label-sm label-warning"> #itm.Status </span>
</td>
</tr>
}
How do i show the title bar along with anchor tag??
Do like this,
"columns": [
{
"name": "Name",
"render": function (data, type, row) {
return "<a href=" + row.myURL+ "/"+ row.id+ "
class='_myCkass' id=" + row.myID + ">" + row.fieldMark + "
</a>";
}
},
{ "data": "CreatedDate" },
//Rest field
],