Update input field total from variable number of input fields in Vue2 - vue.js

I have variable number of input fields for product quantity input generating from API response that takes number as input. I need to update the total price for each items and subtotal for all the items once user changes the input field value.
Here is what i am trying
data:
"productList": [
{
"id": 27,
"product_id": "2362",
"product_name": "nengra",
"unit": "box",
"minimum_order": "1",
"unit_price": "890",
"photo_url": "http://45.114.85.21:11011/micro_product/mv8gigsx2e_7a4i2twgv6.jpg"
},
{
"id": 29,
"product_id": "2365",
"product_name": "nengra",
"unit": "box",
"minimum_order": "1",
"unit_price": "890",
"photo_url": "http://45.114.85.21:11011/micro_product/qdmiugpabf_4ojvtkryym.jpg"
}
]
template:
<div v-for="{{products in productList}}" :key="products.product_id">
<input type="number" v-model="products.qty" v-on:change="updateCart" >
<p>{{products.productsTotal}}</p>
</div>
<p>{{subTotal}}</p>
Script:
data(){
return{
qty:[],
cartID: null,
productList: [],
total: 0,
subtotal: 0,
productTotal: 0
}
},
methods: {
updateCart: function (){
this.products.productTotal = this.products.qty * this.productList.price
}
}
I am very newbee in Vue2 Please help me to sort it out. Thanks

You can use a computed property like this for subTotal:
computed: {
subTotal: function () {
return this.productList.reduce(
(p, np) => p.productTotal + np.productTotal
);
},
},
Pass a reference like v-on:change="updateCart(product)" to clicked product to update it's values:
methods: {
updateCart: function (product) {
product.productTotal = Number(product.qty) * Number(product.unit_price);
},
},
Every time we update the product.productTotal here, subTotal will automatically update since it is a computed property.
Side note: I've added productTotal property to each product. If your data doesn't contain it, you can add it manually in API success callback before setting the data.

Related

v-select with groups from data via api

I get from my API this data:
[
{
"id":69,
"name":"Baupraxis",
"upper_id":7
},
{
"id":42,
"name":"bautipps.de",
"upper_id":4
},
{
"id":16,
"name":"Bellevue",
"upper_id":7
},
{
"id":18,
"name":"besser Bauen",
"upper_id":7
},
{
"id":2,
"name":"Besuch auf Betriebsgel\u00e4nde",
"upper_id":0
},
{
"id":7,
"name":"billiger Bauen",
"upper_id":0
}
]
I use it to fill a v-select like this:
<v-select
label="Anfrageart"
dense
:items="itemsRequestTypes"
item-text="name"
item-value="id"
v-model="requestType"
>
</v-select>
So here's what I'd like to solve, the upper_id is greater than zero if it is a subgroup of an item with the matching id. Means in upper_id is the id of the main group.
How can I group this in a v-select now?
I try to add a header in the object, but this didn't help.
You need to transform your data from the API before passing it to the template. Also, v-select supports nested option group using items where header type represents the group header which is non-selectable item.
const data = [
{
"id": 69,
"name": "Baupraxis",
"upper_id": 7
},
{
"id": 42,
"name": "bautipps.de",
"upper_id": 4
},
{
"id": 16,
"name": "Bellevue",
"upper_id": 7
},
{
"id": 18,
"name": "besser Bauen",
"upper_id": 7
},
{
"id": 2,
"name": "Besuch auf Betriebsgel\u00e4nde",
"upper_id": 0
},
{
"id": 7,
"name": "billiger Bauen",
"upper_id": 0
}
];
// Create an intermediate object to hold categories.
const groups = {};
// Create array for each group to main subgroup list.
data.forEach((x) => {
// create empty object if it doesn't exists.
groups[x.upper_id] = groups[x.upper_id] || { name: x.name, list: [] };
groups[x.upper_id].list.push(x);
});
// The flattened list of items that holds items as well as unique headers
const flattened = [];
// Iterate over all the unique categories and
// then flatten into a list that v-select needs.
Object.keys(groups).forEach((categoryId) => {
const catgory = groups[categoryId];
const categoryName = category.name;
// Create a group
flattened.push({ header: categoryName });
// Add all the items followed by category header
flattened.push(...category.list);
});

Button onClick inside DataTables doesn't show the correct url

I'm displaying all the customer data using DataTables like this:
<script type="text/javascript" src="DataTables/datatables.min.js"></script>
<script>
var theTable = null;
$(document).ready(function() {
theTable = $('#table-customer').DataTable({
"processing": true,
"serverSide": false,
"ordering": true,
"order": [[ 0, 'asc' ]],
"ajax":
{
"url": "http://localhost/myshop/showdata.php",
"type": "GET"
},
"sAjaxDataProp": "data",
"deferRender": true,
"aLengthMenu": [[5, 10, 20, 50],[ 5, 10, 20, 50]],
"columns": [
{ data: "cust_id" },
{ data: "cust_name" },
{ data: "cust_addr" },
{ data: "cust_email" },
{ data: "cust_phone" },
{ data: "cust_photo", sortable: true, render: function (o) { return '<button id="btn1" onclick="displayImage(data)">Show</button>';}
]
});
});
function displayImage(link){
window.alert(link);
}
</script>
All information is displayed properly, except 1 thing: if you click any button on "customer photo" column, instead of showing an alert which shows its URL, nothing happens. Inspecting the page showed me this:
Uncaught ReferenceError: data is not defined
at HTMLButtonElement.onclick (view.html:1)
How to fix this?
The columns.data render function builds a string which is returned:
function (o) { return 'your string here, including data value'; }
You have to (a) concatenate your data variable with the string literals you need; and (b) use the variable name you provided - I will use data instead of o:
function (data) { return 'your string here, including ' + data + ' value'; }
So, if we provide all the possible parameters allowed in the renderer, that becomes:
{
"data": "cust_photo",
"sortable": true,
"render": function(data, type, row, meta) {
return '<button id="btn1" onclick="displayImage(\'' + data + '\')">Show</button>';
}
}
I use \' to ensure the value of the data variable is surrounded in single quotes.
(Note that in your question, the code is also missing a closing }.)
But to avoid potential issues with sorting and filtering, these column data render functions need to account for DataTable's use of orthogonal data.
The type parameter can be used for this:
{
"data": "cust_photo",
"sortable": true,
"render": function(data, type, row, meta) {
if (type === 'display') {
return '<button id="btn1" onclick="displayImage(\'' + data + '\')">Show</button>';
} else {
return data; // type is for sorting or filtering - just use the raw value
}
}
}

Update Amcharts4 chart dynamically using vue js

I'm using AmCharts4 with Vue.JS,
For the moment I've added default chart design when page loads, But when I trying to add dynamic values after page loads (Using Button click), It doesn't reflect on view.
Code:- gist
data: () => ({
dataForChart: {
data: [{
"name": "Anne",
"steps": 32
}, {
"name": "Rose",
"steps": 30
}, {
"name": "Jane",
"steps": 25
}]
}
}),
chart creation on mounted()
let chart = am4core.create("chart-div", am4charts.XYChart);
chart.data = this.dataForChart.data
when dynamically change values using button click those data doesnt reflect on chart.
method followed to change data set.
this.dataForChart.data = {
data: [{
"name": "Anne",
"steps": 54
}, {
"name": "Rose",
"steps": 44
}, {
"name": "Jane",
"steps": 33
}]
}
The reason for this is that although this.dataForChart.data is reactive (it's a vue instance property) the chart.data (amcharts chart property) is not.
You have to manually set chart.data array values whenever your this.dataForChart.data property changes. I've done this by setting a watcher on this.dataForChart.data like so:
watch: {
dataForChart: {
data(values) {
this.chart.data = values;
},
deep: true
}
}
Cheers!

sort dropdown items (response from JSON) in vuejs

Can anyone please suggest me on how to apply sorting to dropdown list in Vue Js
I have used v-select from vuetify
`<v-select v-model='coursesList' :options="courses" :enableDropup="true" options-label="name" options-value="id" name='courseName[]'></v-select>`
mutations:{
setCourseItems (state,response){
state.courseItems=response
}
}
JSON:
[
{
"stock": "available",
"name": "Higher Engineering maths"
},
{
"stock": "available",
"name": "Qantum Physics"
},
{
"stock": "available",
"name": "Biology"
}
]
In javascript you can use the sort method to sort an array.
Here your response seems to be a json array, you can call sort() on it and give it a custom function for sorting. Example :
var myArray = [
{
stock: "available",
name: "Higher Engineering maths"
},
{
stock: "available",
name: "Qantum Physics"
},
{
stock: "available",
name: "Biology"
}
]
myArray.sort(function (item1, item2) => {
//if the result of this method is negative, item2 is considered "bigger" than item1, and vice versa
return item1.name.toLowerCase() < item2.name.toLowerCase() ? -1 : 1
})
this will sort your array by alphabetical order of the name field. Note that toLowerCase() is not necessary but it's advised in case you don't control the input and don't want to treat capital letters differently.

sWidth is not working in dataTables

I am trying to fix column width instead of dataTable choosing it automatically , hence i am trying to set sWidth but its not applying. Following is my code,
$(document).ready(function(){
$('#Emp_table').dataTable()
.columnFilter({
aoColumns: [ {type:"text"},
{ type: "text" },
{ type: "select",bSmart: false,"sType": "string", "sWidth": "5%" },
{ type: "select" },
{ type: "select" },
{ type: "select"},
{ type: "select" },
{ type: "select" }
],
});
});
Here all works fine like filter by text or value except the column width, because of that the table length is extending beyond my page. Even though my first value is ID which is not even more than 3 digits the width takes for around 10 characters . Not only sWidth, even bSmart i am trying to false but still it works with smart filter .
You need to set http://datatables.net/reference/option/autoWidth to false
Also it looks like you're creating your table a bit oddly.
For datatables 1.10 use:
$('#Emp_table').DataTable({
'columns': [
{"type": "string", "width": "5%" },
// etc...
],
'autoWidth': false,
})