In vuejs, quoting variables in HTML element attribute doesn't work - vue.js

Here is the code:
<tr v-for="(item, index) in detail" :key="item.name" class="[[ item.name ]]">
<td>[[ index + 1 ]]</td>
<td>[[ item.name ]]</td>
The rendered HTML looks like this:
<tr class="[[ item.name ]]">
<td>1</td>
<td>Job</td>
</tr>
<tr class="[[ item.name ]]">
<td>2</td>
<td>Jesse</td>
</tr>
<tr class="[[ item.name ]]">
<td>3</td>
<td>Wazert</td>
</tr>
The class="[[ item.name ]]" just don't change. What I expect is:
<tr class="Job">
<td>1</td>
<td>Job</td>
</tr>
<tr class="Jesse">
<td>2</td>
<td>Jesse</td>
</tr>
<tr class="Wazert">
<td>3</td>
<td>Wazert</td>
</tr>
How should I fix it?

First thing Square bracket not worked in vue.js you need to use interpolation for binding the data dynamically.
So you need to use like For Example
HTML
<table border="1">
<tr v-for="(item, index) in detail" :key="item.name" :class="item.name">
<td>{{ index + 1 }}</td>
<td>{{ item.name }}</td>
</tr>
</table>
JS
data: function () {
return {
detail: [{ name: "Job" }, { name: "Jesse" }, { name: "Wazert" }],
};
},
Here you can play with code

You need to use class-binding and interpolate the data:
new Vue({
el: "#app",
data: () => ({
detail: [ { name: "Job" }, { name: "Jesse" }, { name: "Wazert" } ]
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<tr v-for="(item, index) in detail" :key="item.name" :class="item.name">
<td>{{index + 1}}</td>
<td>{{item.name}}</td>
</tr>
</table>
</div>

Related

Vue.js making object.length value reactive

Trying to display Total records. Students.length works the first time on page load thanks to the created() method. However, calling filteredStudents(), is out of date. What is the easiest way to make this reactive?
<template>
<div class="d-inline-flex flex-row p-4 col-2">
Total record(s): {{ recordCount }}
</div>
<table class="table border table-striped table-hover">
<thead class="bg-secondary">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="student in filteredStudents()" :key="student._id">
<td>{{ student.firstName }}</td>
<td>{{ student.lastName }}</td>
<td>{{ student.email }}</td>
</tr>
</tbody>
</table>
</template>
<script>
import MixinCommon from '#/mixins/common.js'
export default {
data() {
return {
searchTerm: '',
Students: [],
studentcount: 0
}
},
created() {
this.Students = this.getSutdentList()
},
computed: {
recordCount() {
return this.Students.length
}
},
mixins: [MixinCommon],
methods: {
filteredStudents() {
return this.searchStudentList(this.searchTerm.toUpperCase(), this.Students)
},
}
}
</script>
I don't know the implementation of the searchStudentsList method, but you could try using the filteredStudents as a computed property, or making a watch property on the searchTerm in order to make the search again:
Using computed:
<template>
<div class="d-inline-flex flex-row p-4 col-2">
Total record(s): {{ recordCount }}
</div>
<table class="table border table-striped table-hover">
<thead class="bg-secondary">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="student in filteredStudents" :key="student._id">
<td>{{ student.firstName }}</td>
<td>{{ student.lastName }}</td>
<td>{{ student.email }}</td>
</tr>
</tbody>
</table>
</template>
<script>
import MixinCommon from '#/mixins/common.js'
export default {
data() {
return {
searchTerm: '',
Students: [],
studentcount: 0
}
},
created() {
this.Students = this.getSutdentList()
},
computed: {
recordCount() {
return this.Students.length
},
filteredStudents() {
return this.searchStudentList(this.searchTerm.toUpperCase(), this.Students)
},
},
mixins: [MixinCommon],
}
</script>
Using watch property:
<template>
<div class="d-inline-flex flex-row p-4 col-2">
Total record(s): {{ recordCount }}
</div>
<table class="table border table-striped table-hover">
<thead class="bg-secondary">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="student in filteredStudents" :key="student._id">
<td>{{ student.firstName }}</td>
<td>{{ student.lastName }}</td>
<td>{{ student.email }}</td>
</tr>
</tbody>
</table>
</template>
<script>
import MixinCommon from '#/mixins/common.js'
export default {
data() {
return {
searchTerm: '',
Students: [],
filteredStudents: [],
studentcount: 0
}
},
created() {
this.Students = this.getSutdentList()
this.filteredStudents = this.searchStudentList(this.searchTerm.toUpperCase(), this.Students)
},
computed: {
recordCount() {
return this.Students.length
}
},
watch: {
searchTerm(newValue) {
this.filteredStudents = this.searchStudentList(newValue.toUpperCase(), this.Students)
}
}
mixins: [MixinCommon],
}
</script>

How to update the value in particular TextBox in Table row using change event in Vue Js

While change the Quantity in the particular TextBox in table row, need to update the calculated Value (Unit Price * Quantity) in another TextBox in the same row.
Template
<template>
<div class="container col-md-12">
<h3>Product List</h3>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Product Name</th>
<th scope="col">Net Content</th>
<th scope="col">MRP</th>
<th scope="col">Discount</th>
<th scope="col">Unit Price</th>
<th scope="col">Quantity</th>
<th scope="col">Value</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<template v-for="group in productgroups">
<tr>
<td colspan="9"><b>{{ group.groupName }}</b></td>
</tr>
<tr v-for="(product, index) in filteredProducts(group.id)" v-bind:key="product.id">
<td class="text-center" scope="row">{{ index + 1 }}</td>
<td>{{ product.productName }}</td>
<td class="text-right">{{ product.netContent }} {{ product.uommasters.uomId }}</td>
<td class="text-right">{{ product.mrp }}</td>
<td class="text-right">{{ product.discountAmount }}</td>
<td class="text-right">
<input type="number" class="form-control" v-bind:id="`salePrice${product.id}`" required name="salePrice" v-model="product.salePrice" readonly />
</td>
<td>
<input type="number" class="form-control" v-bind:id="`quantity${product.id}`" required name="quantity"
#change="getValue(product.id, product.salePrice, product.quantity)" v-model="product.quantity" />
</td>
<td>
<input type="number" class="form-control" :id="'productValue'+product.id" required name="productValue" v-model="product.productValue" readonly />
</td>
</tr>
</template>
</tbody>
</table>
</div>
Script
<script>
import moment from 'moment';
import ProductDataService from "../../services/ProductDataService";
import ProductgroupDataService from "../../services/ProductgroupDataService";
export default {
name: "product-index",
data() {
return {
products: [],
productgroups: [],
productTotal: 0,
};
},
methods: {
getValue(productId, price, qty) {
this.productTotal = price * qty;
alert(this.productTotal);
this.product.discountAmount = this.productTotal;
alert(this.product.discountAmount);
},
filteredProducts(groupId) {
var fproducts = this.products.filter(function(product) {
return product.groupCode == groupId;
});
return fproducts;
},
retreiveProducts() {
ProductDataService.getAll()
.then(response => {
this.products = response.data;
})
.catch(e => {
alert(e);
console.log(e);
})
},
retreiveGroups() {
ProductgroupDataService.getAll()
.then(response => {
this.productgroups = response.data;
})
.catch(e => {
console.log(e);
});
},
},
created() {
this.retreiveProducts();
},
mounted() {
this.retreiveGroups();
},
};
I have populated the products from database using API by grouping and need to update the value while change the quantity using onchange event.

How to get the ID from a table inside a b-modal and display on the page in VUEJS

I am facing issue where i want to get the ID from the table when clicking on the button inside a modal and display it on the main page.
Here is the HTML code
<template>
<div class="hello">
<p>Selected id :</p>
<b-button class="mt-2" variant="primary" v-b-modal.modal-xl>
Select codes
</b-button>
<b-modal id="modal-xl" size="lg" centered hide-footer="true">
<table class="table sortable" data-page-list="[10, 25, 50, 100, all]">
<thead>
<tr>
<th>ID</th>
<th>Code</th>
<th>Button</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2222</td>
<td>
<b-button variant="primary">Select</b-button>
</td>
</tr>
<tr>
<td>2</td>
<td>33333</td>
<td>
<b-button variant="primary">Select</b-button>
</td>
</tr>
<tr>
<td>3</td>
<td>4444</td>
<td>
<b-button variant="primary">Select</b-button>
</td>
</tr>
</tbody>
</table>
</b-modal>
</div>
</template>
Here is the Codesandbox for it.
Any help much appreciated.
One way to do that is to save the selected ID as the local state. In addition, I'd recommend using v-for and an array to store the codes list, and then you can pass the id to the event:
<template>
<div class="hello">
<p>Selected id: {{ selected }}</p>
<b-button class="mt-2" variant="primary" v-b-modal.modal-xl>
Select codes
</b-button>
<b-modal id="modal-xl" size="lg" centered hide-footer="true">
<table class="table sortable" data-page-list="[10, 25, 50, 100, all]">
<thead>
<tr>
<th>ID</th>
<th>Code</th>
<th>Button</th>
</tr>
</thead>
<tbody>
<tr v-for="code in codes" :key="code.id">
<td>{{ code.id }}</td>
<td>{{ code.code }}</td>
<td>
<b-button variant="primary" #click="onSelected(code.id)">Select</b-button>
</td>
</tr>
</tbody>
</table>
</b-modal>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
data() {
return {
codes: [
{id: 1, code: 2222},
{id: 2, code: 3333},
{id: 3, code: 4444},
],
selected: null
}
},
methods: {
onSelected: function(id) {
this.selected = id;
}
}
};
</script>
You can check out a working example here.

VueJs router-link not working, but link copied from it works in another tab

I am building an webapp with VueJs. I have three pages, apps, registries, identities. In the apps page there is a table with apps with a link1 (localhost:8080/apps/{appid}/regs) to view it's registry in each row. Similarly in registry page, there is a link2
(localhost:8080/apps/{appid}/regs/{regid}/ids) to view it's app.
My problem is, when I click on link1 it takes me to the registries page, but when I click on link2 it takes me to localhost:8080 in stead of localhost:8080/apps/{appid}/regs/{regid}/ids. But when I copy the address from link2 and paste in address bar it takes me to the desired page. What am I doing wrong?
Also I am getting following warning in the console -
[Vue warn] missing param for named route "regs": Expected "appid" to
be defined
[Vue warn] missing param for named route "ids": Expected "appid" to be
defined
router.js
{
path: "apps",
name: "apps",
component: () => import("./components/protected/Apps"),
},
{
path: "apps/:appid/regs",
name: "regs",
props: true,
component: () => import("./components/protected/Regs"),
},
{
path: "apps/:appid/regs/:regid/ids",
name: "ids",
props: true,
component: () => import("./components/protected/Ids"),
},
Apps.vue
<template>
<table class="table table-striped mg-b-0">
<thead>
<tr>
<th class="tx-left w-5">#</th>
<th class="tx-left">Application</th>
<th class="tx-left text-center w-5">Action</th>
</tr>
</thead>
<tbody>
<tr v-bind:key="index" v-for="(app, index) in apps">
<td class="masked">{{index+1}}</td>
<td>{{app.name}}</td>
<td class="text-center">
<router-link class="bg-white" :to="{ name: 'regs', params: { appid: app.id}}">
<i class="fa fa-border fa-eye" title="View Registries"/>
</router-link>
</td>
</tr>
</tbody>
</table>
</template>
Regs.vue
<template>
<template v-if="appid">
<table class="table table-striped mg-b-0">
<thead>
<tr>
<th class="tx-left w-5">#</th>
<th class="tx-left">Registry</th>
<th class="tx-left text-center w-5">Action</th>
</tr>
</thead>
<tbody>
<tr v-bind:key="index" v-for="(reg, index) in regs">
<td class="masked">{{index+1}}</td>
<td>{{reg.name}}</td>
<td class="text-center">
<router-link class="bg-white" :to="{ name: 'ids', params: { appid: appid, regid: reg.id}}">
<i class="fa fa-border fa-eye" title="View Identities"/>
</router-link>
</td>
</tr>
</tbody>
</table>
</template>
</template>
<script>
export default {
name: "Regs",
props: ['appid'],
....
}
Ids.vue
<template>
<template v-if="appid && regid">
<table class="table table-striped mg-b-0">
<thead>
<tr>
<th class="tx-left w-5">#</th>
<th class="tx-left">Identity</th>
</tr>
</thead>
<tbody>
<tr v-bind:key="index" v-for="(id, index) in ids">
<td class="masked">{{index+1}}</td>
<td>{{id.name}}</td>
</tr>
</tbody>
</table>
</template>
</template>
<script>
export default {
name: "Ids",
props: ['appid','regid'],
....
}
</script>
It seems that you are already using the props appid' and 'regid' where the props are not yet fully ready in your component itself. Thats why the vue returned a warning.
You could put a condition first before you execute your vfor to ensure that the props has already a value. like this one
Regs.vue
<template v-if="appid">
<tr v-bind:key="index" v-for="(reg, index) in regs">
<td class="masked">{{index+1}}</td>
<td>{{reg.name}}</td>
<td class="text-center">
<router-link class="bg-white" :to="{ name: 'ids', params: { appid: appid,
regid: reg.id}}">
<i class="fa fa-border fa-eye" title="View Identities"/>
</router-link>
</td>
</tr>
</template>
Ids.vue
<template v-if="appid && regid">
<tr v-bind:key="index" v-for="(id, index) in ids">
<td class="masked">{{index+1}}</td>
<td>{{id.name}}</td>
</tr>
</template>

Vue.js 2 filter is not working with data table

Attempting to filter data by the name of the client. Tried many options with no luck. currently i have the list of clients broken out to a separate component with intention to use vuex as the project becomes larger. So with that being said i have currently placed the logic for filtering inside my client info component where as the input for the search is in the clients list component. see below
this is the clients info component
<template>
<tbody class="client-info">
<tr v-for="(client, index) in filterClient" :key="index">
<td>{{ index }}</td>
<td>{{ client.name }}</td>
<td>{{ client.type }}</td>
<td>{{ client.email }}</td>
<td>{{ client.phone }}</td>
<td><router-link v-bind:to="'/client/'+client.id"><i class="far fa-eye"></i></router-link></td>
</tr>
</tbody>
</template>
<script>
export default {
name: 'client-info',
props: {
clients: {
type: Array,
default: () => []
}
},
data() {
return {
search: ''
}
},
created() {
this.$store.dispatch('retrieveClients')
},
computed: {
filterClient () {
return this.clients.filter( client => {
return !this.searchClient || client.name.toLowerCase().includes(this.searchClient.toLowerCase()) > -1
})
}
}
}
</script>
this is the clients list component
<template>
<div>
<!-- this is the head of the table list -->
<table class="table table-bordered table table-light table-striped table-hover">
<thead class="thead-primary">
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Type</th>
<th scope="col">Email</th>
<th scope="col">Phone</th>
<th scope="col">Profile</th>
</tr>
</thead>
<!-- the clients data is imported from client info file -->
<client-info :clients="allClients"></client-info>
</table>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import ClientInfo from '#/components/clientslistexperience/ClientInfo'
export default {
name: 'ClientsList',
components: {
ClientInfo
},
data() {
return {
search: null
}
},
computed: {
...mapGetters(['allClients']),
}
}
</script>
i am aware that the data for the search is placed in both components at the moment, just trying different things out. Also that right now it is not being set up to use vuex for the logic and state. If I am completely off track please let me know!
Table tag requires thead, tbody or tr . it removes other tag , so put table tag inside your component.
<template>
<div>
<client-info :clients="allClients"></client-info>
</div>
</template>
and put table tag along with all inner tag
<template>
<table class="table table-bordered table table-light table-striped table-hover">
<thead class="thead-primary">
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Type</th>
<th scope="col">Email</th>
<th scope="col">Phone</th>
<th scope="col">Profile</th>
</tr>
</thead>
<tbody class="client-info">
<tr v-for="(client, index) in filterClient" :key="index">
<td>{{ index }}</td>
<td>{{ client.name }}</td>
<td>{{ client.type }}</td>
<td>{{ client.email }}</td>
<td>{{ client.phone }}</td>
<td><router-link v-bind:to="'/client/'+client.id"><i class="far fa-eye"></i></router-link></td>
</tr>
</tbody>
</template>