I've built a Vue.js ponent, which fetches orders from a Woomerce store. These orders contain the product variations from the products and are received as an object.
In the table, I need to format the object before it is displayed.
My code looks like this:
<template>
<div>
<vue-good-table
title=""
:columns="columns"
:rows="variationOrders"
:paginate="true"
:lineNumbers="true"/>
</div>
</template>
<script>
export default {
data: function() {
return {
variationOrders: [],
columns: [
{
label: 'Order#',
field: 'order_id',
filterable: true,
},
{
label: 'Customer',
field: 'customer_name',
//type: 'number',
html: false,
filterable: true,
},
{
label: 'QTY',
field: 'qty',
type: 'number',
//inputFormat: 'YYYYMMDD',
//outputFormat: 'MMM Do YY',
},
{
label: 'Product',
field: 'product_name',
//type: 'percentage',
html: false,
},
{
label: 'Variations',
field: this.formatVariations(self.variationOrders),
//type: 'percentage',
html: true,
},
{
label: 'Timeslot',
field: 'timeslot',
//type: 'percentage',
html: false,
},
{
label: 'Transportation',
field: 'store_id',
//type: 'percentage',
html: false,
},
],
}
},
methods: {
getTotals: function() {
var self = this;
var productId = document.getElementById('product-id').getAttribute('data-id');
axios.get('/api/v1/order_variations/' + productId)
.then(function (response) {
self.variationOrders = response.data.order_variations;
//console.log(response.data);
})
.catch(function(error) {
//
});
},
formatVariations: function(variationOrders) {
console.log(variationOrders);
},
},
mounted: function() {
this.getTotals();
// call the API every 30 seconds to fetch new orders
setInterval(function () {
this.getTotals();
}.bind(this), 5000);
}
}
</script>
On the Variations column I pass a function which is responsible for formatting the string. The function itself works fine, but I am unable to pass the the received object from the API to this function.
I get the following error message in the console:
If I pass
this.formatVariations(this.variationOrders)
and console.log I getundefined
If I pass
this.formatVariations(variationOrders)
and console.log I get[Vue warn]: Error in data(): "ReferenceError: variationOrders is not defined"
I have a suspicion that at the time the function is called, that variable doesn't exist yet.
Is there anything I'm missing?
UPDATE 1
I've updated the code to the following. I'm closer but unfortunately the view isn't updating.
MY code looks like this:
<template>
<div>
<vue-good-table
title=""
:columns="formattedColumns"
:rows="variationOrders"
:paginate="true"
:lineNumbers="true"/>
</div>
</template>
<script>
export default {
data: function() {
return {
variationOrders: [],
columns: [
{
label: 'Order#',
field: 'order_id',
filterable: true,
},
{
label: 'Customer',
field: 'customer_name',
//type: 'number',
html: false,
filterable: true,
},
{
label: 'QTY',
field: 'qty',
type: 'number',
//inputFormat: 'YYYYMMDD',
//outputFormat: 'MMM Do YY',
},
{
label: 'Product',
field: 'product_name',
//type: 'percentage',
html: false,
},
{
label: 'Variations',
field: 'variation',
//type: 'percentage',
html: true,
},
{
label: 'Timeslot',
field: 'timeslot',
//type: 'percentage',
html: false,
},
{
label: 'Transportation',
field: 'store_id',
//type: 'percentage',
html: false,
},
],
}
},
methods: {
getTotals: function() {
var self = this;
var productId = document.getElementById('product-id').getAttribute('data-id');
axios.get('/api/v1/order_variations/' + productId)
.then(function (response) {
self.variationOrders = response.data.order_variations;
})
.catch(function(error) {
//
});
},
formatVariations: function(variationOrders) {
var variationsString = '';
variationOrders.forEach(function(item) {
var variations = JSON.parse(item.variation);
for(var i = 0; i < variations.length; i++) {
variationsString = variationsString + variations[i].key + ': ' + variations[i].value + '<br />';
}
});
return variationsString;
},
},
puted: {
formattedColumns(){
const formattedVariations = this.formatVariations(this.variationOrders);
console.log(formattedVariations);
return this.columns.map(c => {
if (c.label == "Variations") {
return {label: "Variations", field: formattedVariations , html: true}
}
return c;
})
}
},
mounted: function() {
this.getTotals();
// call the API every 30 seconds to fetch new orders
setInterval(function () {
this.getTotals();
}.bind(this), 5000);
},
}
</script>
Update 2
The formatVariations() function returns a sample set like this:
choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: No<br />choose-your-cake: Naked<br />choose-sugar: No<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Coated<br />choose-sugar: No<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Coated<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />
Update 3
Here's one array item of what the API returns:
:
customer_name
:
(...)
order_id
:
(...)
product_name
:
(...)
qty
:
(...)
store_id
:
(...)
variation
:
"[{"id": 35, "key": "choose-your-cake", "value": "Naked"}, {"id": 36, "key": "choose-sugar", "value": "Yes"}]"
I've built a Vue.js ponent, which fetches orders from a Woomerce store. These orders contain the product variations from the products and are received as an object.
In the table, I need to format the object before it is displayed.
My code looks like this:
<template>
<div>
<vue-good-table
title=""
:columns="columns"
:rows="variationOrders"
:paginate="true"
:lineNumbers="true"/>
</div>
</template>
<script>
export default {
data: function() {
return {
variationOrders: [],
columns: [
{
label: 'Order#',
field: 'order_id',
filterable: true,
},
{
label: 'Customer',
field: 'customer_name',
//type: 'number',
html: false,
filterable: true,
},
{
label: 'QTY',
field: 'qty',
type: 'number',
//inputFormat: 'YYYYMMDD',
//outputFormat: 'MMM Do YY',
},
{
label: 'Product',
field: 'product_name',
//type: 'percentage',
html: false,
},
{
label: 'Variations',
field: this.formatVariations(self.variationOrders),
//type: 'percentage',
html: true,
},
{
label: 'Timeslot',
field: 'timeslot',
//type: 'percentage',
html: false,
},
{
label: 'Transportation',
field: 'store_id',
//type: 'percentage',
html: false,
},
],
}
},
methods: {
getTotals: function() {
var self = this;
var productId = document.getElementById('product-id').getAttribute('data-id');
axios.get('/api/v1/order_variations/' + productId)
.then(function (response) {
self.variationOrders = response.data.order_variations;
//console.log(response.data);
})
.catch(function(error) {
//
});
},
formatVariations: function(variationOrders) {
console.log(variationOrders);
},
},
mounted: function() {
this.getTotals();
// call the API every 30 seconds to fetch new orders
setInterval(function () {
this.getTotals();
}.bind(this), 5000);
}
}
</script>
On the Variations column I pass a function which is responsible for formatting the string. The function itself works fine, but I am unable to pass the the received object from the API to this function.
I get the following error message in the console:
If I pass
this.formatVariations(this.variationOrders)
and console.log I getundefined
If I pass
this.formatVariations(variationOrders)
and console.log I get[Vue warn]: Error in data(): "ReferenceError: variationOrders is not defined"
I have a suspicion that at the time the function is called, that variable doesn't exist yet.
Is there anything I'm missing?
UPDATE 1
I've updated the code to the following. I'm closer but unfortunately the view isn't updating.
MY code looks like this:
<template>
<div>
<vue-good-table
title=""
:columns="formattedColumns"
:rows="variationOrders"
:paginate="true"
:lineNumbers="true"/>
</div>
</template>
<script>
export default {
data: function() {
return {
variationOrders: [],
columns: [
{
label: 'Order#',
field: 'order_id',
filterable: true,
},
{
label: 'Customer',
field: 'customer_name',
//type: 'number',
html: false,
filterable: true,
},
{
label: 'QTY',
field: 'qty',
type: 'number',
//inputFormat: 'YYYYMMDD',
//outputFormat: 'MMM Do YY',
},
{
label: 'Product',
field: 'product_name',
//type: 'percentage',
html: false,
},
{
label: 'Variations',
field: 'variation',
//type: 'percentage',
html: true,
},
{
label: 'Timeslot',
field: 'timeslot',
//type: 'percentage',
html: false,
},
{
label: 'Transportation',
field: 'store_id',
//type: 'percentage',
html: false,
},
],
}
},
methods: {
getTotals: function() {
var self = this;
var productId = document.getElementById('product-id').getAttribute('data-id');
axios.get('/api/v1/order_variations/' + productId)
.then(function (response) {
self.variationOrders = response.data.order_variations;
})
.catch(function(error) {
//
});
},
formatVariations: function(variationOrders) {
var variationsString = '';
variationOrders.forEach(function(item) {
var variations = JSON.parse(item.variation);
for(var i = 0; i < variations.length; i++) {
variationsString = variationsString + variations[i].key + ': ' + variations[i].value + '<br />';
}
});
return variationsString;
},
},
puted: {
formattedColumns(){
const formattedVariations = this.formatVariations(this.variationOrders);
console.log(formattedVariations);
return this.columns.map(c => {
if (c.label == "Variations") {
return {label: "Variations", field: formattedVariations , html: true}
}
return c;
})
}
},
mounted: function() {
this.getTotals();
// call the API every 30 seconds to fetch new orders
setInterval(function () {
this.getTotals();
}.bind(this), 5000);
},
}
</script>
Update 2
The formatVariations() function returns a sample set like this:
choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: No<br />choose-your-cake: Naked<br />choose-sugar: No<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Coated<br />choose-sugar: No<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Coated<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />choose-your-cake: Naked<br />choose-sugar: Yes<br />
Update 3
Here's one array item of what the API returns:
:
customer_name
:
(...)
order_id
:
(...)
product_name
:
(...)
qty
:
(...)
store_id
:
(...)
variation
:
"[{"id": 35, "key": "choose-your-cake", "value": "Naked"}, {"id": 36, "key": "choose-sugar", "value": "Yes"}]"
Share
Improve this question
edited Oct 12, 2017 at 15:19
Marcus Christiansen
asked Oct 12, 2017 at 12:03
Marcus ChristiansenMarcus Christiansen
3,2079 gold badges52 silver badges93 bronze badges
1 Answer
Reset to default 7self.variationOrders
is undefined in the data method; self
is only available in the scope of the getTotals
method.
Instead, use a puted property to format columns
.
puted:{
formattedColumns(){
const formattedVariations = this.formatVariations(this.variationOrders)
return this.columns.map(c => {
if (c.label === "Variations")
return {label: "Variations", field: formattedVariations , html: true}
return c
})
}
}
And use the puted property in the template.
<vue-good-table
title=""
:columns="formattedColumns"
:rows="variationOrders"
:paginate="true"
:lineNumbers="true"/>
The puted property should be updated whenever variationOrders
changes.
Edit
The above answers the question that was asked, but doesn't actually render the desired table (as I understand it). This is because of a misunderstanding in how vue-good-table
works.
If I understand correctly, what OP really wants is for the content of the cell in the table to be formatted with HTML. In order to do that, you simply need to use the scoped slot table-row
. Here is how the template should look (the columns are abbreviated for this example).
<vue-good-table
title=""
:columns="columns"
:rows="variationOrders"
:paginate="true"
:lineNumbers="true">
<template slot="table-row" scope="props">
<td>{{ props.row.order_id }}</td>
<td>{{ props.row.customer_name }}</td>
<td><span v-html="formatVariations(props.row.variation)"></span></td>
</template>
</vue-good-table>
I also updated the formatVariations
method:
formatVariations: function(variationOrders) {
let parsed = JSON.parse(variationOrders).map(order => {
return `${order.key} : ${order.value} <br>`
})
return parsed.join('');
},
This is assuming the data format looks like this:
[
{
order_id: 1,
customer_name: "Bob NewHart",
qty: 10,
product_name: "Hats",
variation: '[{"id": 35, "key": "choose-your-cake", "value": "Naked"}, {"id": 36, "key": "choose-sugar", "value": "Yes"}]'
},
{
order_id: 2,
customer_name: "Mary Lamb",
qty: 10,
product_name: "Necklaces",
variation: '[{"id": 35, "key": "choose-your-cake", "value": "Naked"}, {"id": 36, "key": "choose-sugar", "value": "Yes"}]'
},
]