Let's assume that the product information of our users can be changed by users. When the name is changed to any of the products of the customer, it is not reflected instantly. It is reflected when the page is refreshed. What is the solution?
<template>
<div>
<table>
<thead>
<tr>
<th scope="col">
<span>Name</span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="(customer,n) in customers" :key="n">
<td>
<div>
<p>{{ !customer?.product?.productName ? "" : customer?.products?.productName }}
</div>
</td>
</tr>
</tbody>
</div>
</template>
<script>
export default {
data() {
return {
customers: [
{
name: 'Jack', surname: 'Bruyne',
products: [
{i: 1, productName: 'home'},
{i: 2, productName: 'car'},
{i: 3, productName: 'yatch'},
{i: 4, productName: 'villa'},
]
}
],
}
},
}
</script>
The objects returned by data() function is reactive; the UI will update when the underlying data object changes. In your code, you do not show the products in the UI. Since you have an array of customers and each customer has an array of products, you need two v-fors.
The following code shows the products of each user, and the button changes a random product name from a given list. As you can see, the UI is updated automatically:
<div>
<table>
<thead>
<tr>
<th scope="col">
<span>Name</span>
</th>
<th>Products</th>
</tr>
</thead>
<tbody>
<tr v-for="(customer,n) in customers" :key="n">
<td>
<p>{{customer.name}}</p>
</td>
<td>
<span v-for="product in customer.products" :key="product.i">
{{product.productName}},
</span>
</td>
</tr>
</tbody>
</div>
<button #click="changeProduct">Swap random product</button>
</div>
<script>
methods: {
changeProduct() {
const personId = Math.floor(Math.random() * 2);
const productId = Math.floor(Math.random() * 4);
const randomId = Math.floor(Math.random() * 8);
this.customers[personId].products[productId].productName = this.randomProducts[randomId];
}
},
data() {
return {
randomProducts: ["car", "home", "yacht", "villa", "PC", "batmobile", "keyboard", "stuff"],
customers: [
{
name: 'Jack', surname: 'Bruyne',
products: [
{i: 1, productName: 'home'},
{i: 2, productName: 'car'},
{i: 3, productName: 'yatch'},
{i: 4, productName: 'villa'},
]
},
{
name: 'John', surname: 'Doe',
products: [
{i: 1, productName: 'PC'},
{i: 2, productName: 'batmobile'},
{i: 3, productName: 'Keyboard'},
{i: 4, productName: 'stuff'},
]
}
],
}
}
})
</script>
Related
I have some menus in table. There are some sub-menus under the menus. I want to display them in a table. I am trying this--
new Vue({
el: '#app',
data: function() {
return {
menus: [
{ id: 1, menuName: "Tech 1" },
{ id: 2, menuName: "Tech 2" },
{ id: 3, menuName: "Tech 3" }],
selectedMenu: [],
submenus: [
{ id: 1, menuId: 1, subMenuName:"architecture" },
{ id: 2, menuId: 1, subMenuName:"Electrical" },
{ id: 3, menuId: 1, subMenuName:"Electrical" },
{ id: 4, menuId: 2, subMenuName:"IEM" },
{ id: 5, menuId: 3, subMenuName:"CIVIL"}],
}
},
computed: {
filteredProduct: function () {
const app = this,
menu = app.selectedMenu;
if (menu.includes("0")) {
return app.submenus;
} else {
return app.submenus.filter((p) => menu.includes(p.menuId));
}
},
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"
><div id="app">
<table class="table">
<thead>
<tr>
<th>Menu</th>
<label><input type="checkbox" v-model="selectedMenu" value="0" />
All</label</th>
<th>Submenu</th>
</tr>
</thead>
<tbody>
<tr v-for="menu in menus" :key="menu.id">
<td>
<label>
<input
type="checkbox"
:value="menu.id"
v-model = "selectedMenu"
/>{{ menu.menuName }}
</label
>
</td>
<td>
<ul>
<li
v-for="submenu in filteredProduct"
:key="submenu.id">
<input type="checkbox" :value="submenu.id"/>
<label>{{ submenu.subMenuName }} </label>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
My problem is, When I click on any menu, The submenus are showing on other columns too.
When I click on any menu, the submenus associated with that menu should display in that particular row. How do I do this?
You should add Submenu Object inside Menus. for your data object i have updated code as below. you need to maintain the selected menu id to toggle the submenus.
var app = new Vue({
el: "#app",
data: {
menus: [
{ id: 1, menuName: "Tech 1" },
{ id: 2, menuName: "Tech 2" },
{ id: 3, menuName: "Tech 3" }],
selectedMenu: [],
submenus: [
{ id: 1, menuId: 1, subMenuName:"architecture" },
{ id: 2, menuId: 1, subMenuName:"Electrical" },
{ id: 3, menuId: 1, subMenuName:"Electrical" },
{ id: 4, menuId: 2, subMenuName:"IEM" },
{ id: 5, menuId: 3, subMenuName:"CIVIL"}],
},
computed: {
filteredProduct: function () {
const app = this,
menu = app.selectedMenu;
if (menu.includes("0")) {
return app.submenus;
} else {
return app.submenus.filter(function(item){
return menu.indexOf(item.menuId) >= 0;
});
}
},
},
methods: {
setSelectedMenu:function(event,menu_id){
if (event.target.checked) {
this.selectedMenu.push(menu_id);
}
else{
var index= this.selectedMenu.indexOf(menu_id);
this.selectedMenu.splice(index,1);
}
}
}
})
Here is HTML :
<table class="table">
<thead>
<tr>
<th>Menu</th>
<label><input type="checkbox" v-model="selectedMenu" value="0" />
All</label>
<th>Submenu</th>
</tr>
</thead>
<tbody>
<tr v-for="menu in menus" :key="menu.id">
<td>
<label>
<input
type="checkbox"
:value="menu.id" #change="setSelectedMenu($event,menu.id)"
/>#{{ menu.menuName }}
</label
>
</td>
<td >
<ul>
<li
v-for="submenu in filteredProduct"
:key="submenu.id" v-if="menu.id == submenu.menuId">
<input type="checkbox" :value="submenu.id" />
<label >{{ submenu.subMenuName }} </label>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
I have also created working fiddle:
https://jsfiddle.net/n9502h71/1/
Also if you want to select multiple values you should push selected values in array.
I want to show the total amount from the data, but how can I do it with vue js in the simplest way?
There is a field where I need to write the sum of the balance amounts, but I cannot do much because the room is outside the for.
const app = new Vue({
el: '#app',
data: {
userList: [{
id: 1,
name: "Prem",
gender: "male",
balance:'3522'
},
{
id: 2,
name: "Chandu",
gender: "female",
balance:'2762'
},
{
id: 3,
name: "Jong",
gender: "female",
balance:'2000'
},
{
id: 4,
name: "Steew",
gender: "male",
balance:'2000'
},
{
id: 5,
name: "Abdollah",
gender: "female",
balance:'2000'
},
{
id: 6,
name: "Jerry",
gender: "male",
balance:'1500.5'
}
]
}
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<script src="https://unpkg.com/vue-router#2.0.0/dist/vue-router.js"></script>
<div id="app">
<table class="table table-hover table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Gender</th>
<th>Pice</th>
</tr>
</thead>
<tbody>
<tr v-for="(user, i) in userList" class="position-relative">
<td>{{ user.name }}</td>
<td>{{ user.gender }}</td>
<td>{{user.balance}}<td>
</tr>
</tbody>
<tfoot>
<tr>
<td>total number of records: {{userList.length}}</td>
<td></td>
<td>Total:</td>
</tr>
</tfoot>
</table>
</div>
Define total as a computed property using reduce function as follows :
data: {
userList: [...],
},
computed:{
total(){
return this.userList.reduce((acc,curr)=>{
return acc+=(+curr)
},0)
}
}
}
in template :
<td>Total: {{total}}</td>
I’m not sure If I am doing this correctly but I am trying to collect an Array of Id’s that I will use to update data on my back end,
I implemented checkboxes but I do not know how to add support when parent checkbox is selected to select all children checkbox , and also when select all children checkbox to select parent checkbox ?
here is i'm tried this so far:
export default {
data() {
return {
userlistes: [
{
id: 2,
username: "Larry",
department_id: 3,
department: {
department_name: "IT",
id: 3,
},
worklists: [
{
id: 278,
user_id: 2,
task_id: 1,
date: "2021-07-30",
hour: 2,
description: "A",
is_overtime: false,
overtime_hour: 0,
task: {
taskname: "Task A",
},
hr_checked: false,
},
{
id: 277,
user_id: 2,
task_id: 1,
date: "2021-07-30",
hour: 3,
description: "B",
is_overtime: false,
overtime_hour: 0,
task: {
taskname: "Task B",
},
hr_checked: false,
},
],
},
{
id: 4,
username: "Tom",
department_id: 2,
department: {
department_name: "Business",
id: 2,
},
worklists: [
{
id: 259,
user_id: 4,
task_id: 7,
date: "2021-07-27",
hour: 6.5,
description:
"A",
is_overtime: false,
overtime_hour: 0,
task: {
taskname: "Task A",
},
hr_checked: false,
},
{
id: 260,
user_id: 4,
task_id: 7,
date: "2021-07-27",
hour: 0.5,
description: "B",
is_overtime: false,
overtime_hour: 0,
task: {
taskname: "Task B",
},
hr_checked: false,
},
],
},
],
isChecklist: [],
checkAll: false,
};
},
methods: {
clickCheckAll() {
var _this = this;
_this.checkAll = !_this.checkAll;
for (var i = 0; i < _this.userlistes.worklists.length; i++) {
var checkedData = _this.userlistes.worklists[i];
checkedData.hr_checked = _this.checkAll;
updateWorkhourAPI(checkedData.id, checkedData);
}
},
clickCheckbox(id, worklist) {
var _this = this;
worklist.hr_checked = !worklist.hr_checked;
if (worklist.manager_checked) {
_this.isChecklist.push(id);
updateWorkhourAPI(id, worklist);
} else {
var last = _this.isChecklist.length - 1;
_this.isChecklist.splice(last, 1);
updateWorkhourAPI(id, worklist);
}
if (_this.isChecklist.length == _this.userlistes.length) {
_this.checkAll = true;
} else {
_this.checkAll = false;
}
},
},
};
<b-card no-body class="mb-1" v-for="users in userlistes" :key="users.id">
<b-card-header header-tag="header" class="p-0" role="tab">
<div class="d-grid gap-2">
<b-button
block
variant="outline-primary"
v-b-toggle="`accordion-${users.id}`"
>
{{ users.username }}
</b-button>
</div>
</b-card-header>
<b-collapse
:id="`accordion-${users.id}`"
accordion="table-accordion"
role="tabpanel"
>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th colspan="10">
<h3 style="text-align: center">
{{ users.username }} Work-Lists
</h3>
</th>
</tr>
<tr>
<th>Task Name</th>
<th>Date</th>
<th>Description </th>
<th>Hour (hr)</th>
<th>Overtime </th>
<th>Overtime Hour (hr)</th>
<th>
<label class="form-checkbox">
<input
type="checkbox"
#click="clickCheckAll()"
v-model="checkAll"
/>
<i class="form-icon"></i>
</label>
</th>
</tr>
</thead>
<tbody>
<tr v-for="worklist in users.worklists" :key="worklist.id">
<td>{{ worklist.task.taskname }}</td>
<td>{{ worklist.date }}</td>
<td>{{ worklist.description }}</td>
<td>{{ worklist.hour }}</td>
<td>{{ worklist.is_overtime ? "Yes" : "No" }}</td>
<td>{{ worklist.overtime_hour }}</td>
<td>
<label class="form-checkbox">
<input
type="checkbox"
#click="clickCheckbox(worklist.id, worklist)"
v-model="worklist.hr_checked"
/>
<i class="form-icon">
{{ worklist.hr_checked }}
</i>
</label>
</td>
</tr>
</tbody>
</table>
</b-collapse>
</b-card>
i figured it out how to solve this problem: count array index ,
thanks advanced
<b-card no-body class="mb-1" v-for="(users, idx) in userlistes" :key="users.id">
<b-collapse
:id="`accordion-${users.id}`"
accordion="table-accordion"`enter code here`
role="tabpanel"
>
<table class="table table-striped table-bordered">
<thead>
<th>
<label class="form-checkbox">
<input
type="checkbox"
#click="clickCheckAll(idx)"
:value="allChecked(idx)"
/>
<i class="form-icon"></i>
</label>
</th>
</tr>
</thead>
</table>
</b-collapse>
</b-card>
export default {
data() {
return { //.. };
},
methods: {
allChecked(idx) {
return this.userlistes[idx].worklists.some((el) => el.hr_checked)
},
clickCheckAll(idx) {
this.checkAll = !this.checkAll;
const currentUser = this.userlists[idx]
for (let i = 0; i < currentUser.worklists.length; i++) {
currentUser.worklists[i].hr_checked = this.checkAll;
}
},
},
}
Guys I'm starting with Vue and I'm having a little difficulty. In the image below I have a table with some items and when I will increase the amount of the item Orange for example is increased all other items, how to fix it?
enter image description here
My code
new Vue({
el: '#app',
data() {
return {
quantity: 1,
fruits: [
{ Code: 1, Name: 'Abacaxi', Price: "50.00" },
{ Code: 2, Name: 'Abacate', Price: "50.00" },
{ Code: 3, Name: 'Morango', Price: "60.00" },
{ Code: 4, Name: 'Maçã', Price: "17.00" },
{ Code: 5, Name: 'Laranja', Price: "30.00" }
]
}
},
methods: {
add() {
this.quantity++
},
remove() {
if(this.quantity === 0) {
this.quantity = 0
} else {
this.quantity--
}
}
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<template>
<div class="user-list">
<table>
<thead>
<tr>
<th>#Code</th>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr v-for="fruit in fruits" :key="fruit.Code">
<td>
<button #click="remove">-</button>
<input type="text" :value="quantity">
<button #click="add">+</button>
</td>
<td>{{ fruit.Name }}</td>
<td>{{ fruit.Price }}</td>
</tr>
</tbody>
</table>
</div>
</template>
</div>
You should just need to have a quantity on each item in your list. You'd then pass the relevant item to add or remove.
new Vue({
el: '#app',
data() {
return {
fruits: [
{ Code: 1, Name: 'Abacaxi', Price: "50.00", quantity: 1 },
{ Code: 2, Name: 'Abacate', Price: "50.00", quantity: 1 },
{ Code: 3, Name: 'Morango', Price: "60.00", quantity: 1 },
{ Code: 4, Name: 'Maçã', Price: "17.00", quantity: 1 },
{ Code: 5, Name: 'Laranja', Price: "30.00", quantity: 1 }
]
}
},
methods: {
add(fruit) {
fruit.quantity++
},
remove(fruit) {
if(fruit.quantity !== 0) {
fruit.quantity--
}
}
}
})
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<div id="app">
<template>
<div class="user-list">
<table>
<thead>
<tr>
<th>#Code</th>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr v-for="fruit in fruits" :key="fruit.Code">
<td>
<button #click="remove(fruit)">-</button>
<input type="text" v-model.number="fruit.quantity">
<button #click="add(fruit)">+</button>
</td>
<td>{{ fruit.Name }}</td>
<td>{{ fruit.Price }}</td>
</tr>
</tbody>
</table>
</div>
</template>
</div>
I've also switched :value to v-model.number, which seems more likely to be what you'd want though it's not directly related to the problem mentioned in the question.
I have a table which show product name and quantity and price and total price. I had written logic of total cost as formula cost *quantity. i have a button outside of table which is by default hidden by using v-if directive how can i make that button active if only at least one product quantity is greater than zero. By default i had given 0 as quantity because it will vary according to user. I have array of products in v-for loop i iterated as v-for="p in products" so quantity will be p.quantity. how can i use that p.quantity also from outside of loop
## Html table ##
<table class="table table-striped">
<thead>
<tr>
<td>S.No#</td>
<td>Product</td>
<td>Cost</td>
<td>Quantity</td>
<td>Total</td>
</tr>
</thead>
<tbody>
<tr v-for="p in products">
<td>1</td>
<td>{{p.item}}</td>
<td>{{p.cost}}</td>
<td><input type="number" class="form-control qty-box" name="" v-model='p.qt' min="0"></td>
<td>{{p.cost*p.quantity}}</td>
</tr>
</tbody>
</table>
<div class="row">
<div class="col-md-12">
<center v-if="btn"><button class="btn btn-success">Confirm</button></center>
</div>
</div>
## Vue-cli Code ##
<script>
export default {
name: 'app',
data () {
return {
btn:false,
counter:8,
qty:0,
proTotal:'',
products:[
{'item':'timber','cost':250,'id':1, 'quantity ':0},
{'item':'wood','cost':240,'id':2, 'quantity ':0},
{'item':'primer','cost':120,'id':3, 'quantity ':0},
{'item':'plywood','cost':360,'id':4, 'quantity ':0},
{'item':'marker','cost':220,'id':5, 'quantity ':0},
{'item':'roughwood','cost':480,'id':6, 'quantity ':0},
],
msg: 'Counter',
}
},
mounted:function(){
this.bill();
},
methods:{
bill(){
this.qty = this.p.quantity;
if(this.qty>0){
btn:true;
}
}
}
}
</script>
That's a good use case for computed properties:
computed: {
showButton() {
var showButton = false;
this.products.forEach(product => {
if (product.quantity > 0) {
showButton = true;
}
});
return showButton;
}
}
Also, you have to add number to v-model so it's not stored as string.
Your whole code would look like this:
<template>
<div id="about">
<table class="table table-striped">
<thead>
<tr>
<td>S.No#</td>
<td>Product</td>
<td>Cost</td>
<td>Quantity</td>
<td>Total</td>
</tr>
</thead>
<tbody>
<tr v-for="(p, index) in products" :key="index">
<td>1</td>
<td>{{p.item}}</td>
<td>{{p.cost}}</td>
<td><input type="number" class="form-control qty-box" name="" v-model.number='p.quantity' min="0"></td>
<td>{{p.cost*p.quantity}}</td>
</tr>
</tbody>
</table>
<div class="row">
<div class="col-md-12">
<p v-if="showButton">
<button class="btn btn-success">Confirm</button>
</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: "app",
data() {
return {
btn: false,
counter: 8,
qty: 0,
proTotal: "",
products: [
{ item: "timber", cost: 250, id: 1, quantity: 0 },
{ item: "wood", cost: 240, id: 2, quantity: 0 },
{ item: "primer", cost: 120, id: 3, quantity: 0 },
{ item: "plywood", cost: 360, id: 4, quantity: 0 },
{ item: "marker", cost: 220, id: 5, quantity: 0 },
{ item: "roughwood", cost: 480, id: 6, quantity: 0 }
],
msg: "Counter"
};
},
computed: {
showButton() {
var showButton = false;
this.products.forEach(product => {
if (product.quantity > 0) {
showButton = true;
}
});
return showButton;
}
}
};
</script>