Data is not showing up in html - vue.js

I am running into a issue with showing the data from my variable, itemListPrice. I have checked in the console and the data is populated into the itemListPrice, but its not showing up in my html, am I loading it all wrong?
Here is the markup
<div id="app2">
<div id="TableContainer" style="width:798px !important">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<td><label>Catalog Name</label></td>
</tr>
</thead>
<tbody>
<tr>
<td>{{ currentCatalogName }}</td>
</tr>
</tbody>
</table>
<table class="table">
<thead>
<tr>
<td><label>Item Name</label></td>
</tr>
</thead>
<tbody>
<tr>
<td> {{ itemPriceList.Name }}</td>
</tr>
</tbody>
</table>
<table class="table">
<thead>
<tr>
<td colspan="2"><label>Item List</label></td>
</tr>
</thead>
<tbody>
<tr>
<td width="575px">${{ itemPriceList.ItemListPrice }}</td>
<td>${{ itemPriceList.ItemListPrice }}</td>
</tr>
</tbody>
</table>
<table class="table">
<thead>
<tr>
<td colspan="3"><label>Item Features</label></td>
<td></td>
</tr>
</thead>
<tbody>
<template v-for="item in itemPriceList.ItemFeatures">
<tr v-if="item.FeatureQuantity != 0">
<td width="250px">{{ item.FeatureName }}</td>
<td>{{ item.FeatureQuantity }}</td>
</tr>
</template>
</tbody>
</table>
<table class="table">
<thead>
<tr>
<td><label>Item IAM</label></td>
</tr>
</thead>
<tbody>
<tr>
<td>{{ itemPriceList.ItemIAM }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
and here is my code
new Vue({
el: '#app2',
beforeCreate: function () {
StartBusyIndicator("#ItemPriceListWindow");
},
created: function () {
this.GetItemDetails();
},
mounted: function () {
StopBusyIndicator("#ItemPriceListWindow");
},
data: {
itemPriceList: [],
orderItems: currentOrderItems,
currentCatalogName: currentCatalog,
priceList: null
},
methods: {
GetItemDetails: function () {
TryCatch(function() {
let result = GetItemPriceDetails();
this.itemPriceList = result;
priceList = result;
});
},
GetOrderItems: function () {
},
OptionPriceSplitter: function (optionprice) {
return TryCatch(function() {
let sentenceSplit = optionprice.split('& ');
let comp = '';
for (let i = 0; i < sentenceSplit.length; i++) {
comp += sentenceSplit[i] + '\n';
}
return sentenceSplit;
});
},
GlobalListPriceCalculation: function (globalgroupid) {
return TryCatch(function() {
let listPrice = 0.00;
let priceList = this.itemPriceList;
let result = priceList.GlobalListPrices.filter(function(item) {
if (item.GlobalGroupID == globalgroupid) {
listPrice = listPrice + item.Price;
}
});
if (listPrice == 0) {
listPrice = "";
} else {
listPrice = "$" + listPrice.toFixed(2);
}
return listPrice;
});
}
}
});

assuming TryCatch(cb) is something along the lines of
function TryCatch(cb){ let x = null; try { x = cb() } catch(e) {} return x; }
you loose 2 important things:
this (you could bind it via cb.call(this))
utterly usefull error messages
furher points:
I have checked in the console
checkout the excellent browser plugin for ff and chrome vue-devtools
itemPriceList = []
you initalize itemPriceList as array, use it as array item in itemPriceList, but also use it as object {{ itemPriceList.Name }} - what shall it be ?

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.

change button switch toggle in vuejs

I have a button that when I click it changes the status of the record, but when I update, the color of the button does not change, if I refresh the page if it changes, how can I make the button change when I update the record
Table:
<div class="card-body">
<table id="tblProfiles" class="table table-bordered table-hover dt-responsive">
<thead>
<tr>
<th>Description</th>
<th>Status</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr v-for="(profile, index) in profiles" :key="index">
<td>{{ profile.description }}</td>
<td>
<button
class="btn-sm"
:class="[profile.status == 1 ? 'btn-success' : 'btn-danger']"
#click="statusUpdate(profile.id)"
>{{profile.status == 1 ? 'Active' : 'Inactive'}}
</button>
</td>
<td>
<button class="btn btn-info btn-sm">Details</button>
</td>
</tr>
</tbody>
</table>
</div>
Method:
// ...
statusUpdate: async function(id) {
try {
const response = await profileService.activateDesactivate(id);
console.log(response);
} catch (error) {
console.log(error);
}
}
Send profile object insted of id prop:
<div class="card-body">
<table id="tblProfiles" class="table table-bordered table-hover dt-responsive">
<thead>
<tr>
<th>Description</th>
<th>Status</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr v-for="(profile, index) in profiles" :key="index">
<td>{{ profile.description }}</td>
<td>
<button
class="btn-sm"
:class="[profile.status == 1 ? 'btn-success' : 'btn-danger']"
#click="statusUpdate(profile)"
>{{profile.status == 1 ? 'Active' : 'Inactive'}}
</button>
</td>
<td>
<button class="btn btn-info btn-sm">Details</button>
</td>
</tr>
</tbody>
</table>
</div>
Method receives profile objetc and update it as you want. In your case status prop changes the color class of your button.
statusUpdate: async function(profile) {
try {
const response = await profileService.activateDesactivate(profile.id);
profile.status = 1;
console.log(response);
} catch (error) {
console.log(error);
}
},

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>

vueJS hide element in dynamic table row

I have a table that looks like this:
<table class="table">
<thead>
<tr>
<td><strong>Title</strong></td>
<td><strong>Job</strong></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows">
<td><p class="title">My title</p></td>
<td><input type="text" v-model="row.job"></td>
<td><a #click="title()">Remove title</a></td>
</tr>
</tbody>
</table>
Now I wonder how I can toggle a jquery .hide() on the <p class="title">My title</p> when the remove title link is clicked on.
I dont want to use v-show since I am trying to understand how I can target elements within dynamic generated rows in vueJS.
The problem is that there are many rows in my table so every title tag must have a uniqe class and I dont understand how I can hide a specific title on dynamic generated rows
Can be done this way using v-show directive.
new Vue({
el: '.table',
data: {
rows: [
{ showTitle: true, job: 'A' },
{ showTitle: true, job: 'B' },
{ showTitle: true, job: 'C' }
]
}
});
<script src="https://unpkg.com/vue#2.5.2/dist/vue.min.js"></script>
<table class="table">
<thead>
<tr>
<td><strong>Title</strong></td>
<td><strong>Job</strong></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows">
<td><p v-show='row.showTitle' class="title">My title</p></td>
<td><input type="text" v-model="row.job"></td>
<td><a #click="row.showTitle = false">Remove title</a></td>
</tr>
</tbody>
</table>
Edit:
Here is jQuery version but as I already said this is a bad practice.
new Vue({
el: '.table',
data: {
rows: [
{ job: 'A' },
{ job: 'B' },
{ job: 'C' }
]
},
methods: {
hideTitle(index) {
$(this.$refs['title' + index]).hide();
}
}
});
<script src="https://unpkg.com/vue#2.5.2/dist/vue.min.js"></script>
<script src="https://unpkg.com/jquery#3.2.1/dist/jquery.min.js"></script>
<table class="table">
<thead>
<tr>
<td><strong>Title</strong></td>
<td><strong>Job</strong></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows">
<td><p class="title" :ref="'title' + index">My title</p></td>
<td><input type="text" v-model="row.job"></td>
<td><a #click="hideTitle(index)">Remove title</a></td>
</tr>
</tbody>
</table>
Try this one. it works. using v-f and title model
template
<table class="table">
<thead>
<tr>
<td><strong>Title</strong></td>
<td><strong>Job</strong></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows">
<td v-if="title === false"><p class="title">My title</p></td>
<td><input type="text" v-model="row.job"></td>
<td><a #click="title()">Remove title</a></td>
</tr>
</tbody>
</table>
script
data () {
title:false,
},
methods: {
title(){
this.title= true
}
}
As others have mentioned, mixing jQuery and Vue is not the best idea. However, if you must, you can use the event.target that #flypan mentioned along with some jQuery selectors to get what you want.
I put together a JSFiddle using your HTML as an example of what can be done:
new Vue({
el: '#app',
data: {
rows: [
{ job: 'A' }, { job: 'B' }
]
},
methods: {
title: function() {
$title = $(event.target).parent().parent().find("p");
$($title).hide();
}
}
});
You would probably want to tighten the selector to find the "p", but this is just an example. Here's the working JSFiddle:
https://jsfiddle.net/psteele/p5Lpxj5a/
For conditionally displaying, you can use v-show directive,document link here :
v-show doucment.
Hope this can be helpful to you!