link3014 link3015 link3016 link3017 link3018 link3019 link3020 link3021 link3022 link3023 link3024 link3025 link3026 link3027 link3028 link3029 link3030 link3031 link3032 link3033 link3034 link3035 link3036 link3037 link3038 link3039 link3040 link3041 link3042 link3043 link3044 link3045 link3046 link3047 link3048 link3049 link3050 link3051 link3052 link3053 link3054 link3055 link3056 link3057 link3058 link3059 link3060 link3061 link3062 link3063 link3064 link3065 link3066 link3067 link3068 link3069 link3070 link3071 link3072 link3073 link3074 link3075 link3076 link3077 link3078 link3079 link3080 link3081 link3082 link3083 link3084 link3085 link3086 link3087 link3088 link3089 link3090 link3091 link3092 link3093 link3094 link3095 link3096 link3097 link3098 link3099 link3100 link3101 link3102 link3103 link3104 link3105 link3106 link3107 link3108 link3109 link3110 link3111 link3112 link3113 link3114 link3115 link3116 link3117 link3118 link3119 link3120 link3121 link3122 link3123 link3124 link3125 link3126 link3127 link3128 link3129 link3130 link3131 link3132 link3133 link3134 link3135 link3136 link3137 link3138 link3139 link3140 link3141 link3142 link3143 link3144 link3145 link3146 link3147 link3148 link3149 link3150

[Vue.js] How to display data from the nested object in Vue.js based on click event

there is an array with 3 objects inside. Each object has 4 properties:

buttons: [
{
id: ‘btn1’,
name: ‘button-1’,
number: 1,
color: ‘red’
},
{
id: ‘btn2’,
name: ‘button-2’,
number: 2,
color: ‘blue’
},
{
id: ‘btn3’,
name: ‘button-3’,
number: 3,
color: ‘orange’
}
]

In my html there is 3 buttons, each one connected to the given object.

<button id=”btn1” name=”” number=”” color=””>One</button>
<button id=”btn2” name=”” number=”” color=””>Two</button>
<button id=”btn3” name=”” number=”” color=””>Two</button>

<hr>

<h2>Clicked button data:</h2>

<p>{ id }</p>
<p>{ name }</p>
<p>{ number }</p>
<p>{ color }</p>

How can I display data for the given object based on the clicked button?

Here is a snippet with my code:

https://jsfiddle.net/marektchas/rqjxpav2/1/

Solution :

It is pretty simple. You just need to attach an event listener with the @ prefix. That listener must be a method defined in the methods object on the vue.js object. Then you can just let the method receive the button object as a parameter. In my example I added a current property that is set by the method and contains the last pressed button. I also replaced the four buttons with one input and a v-for directive but it also works with buttons.

var app = new Vue({
el: ‘#app’,
data: {
buttons: [{
id: ‘btn1’,
name: ‘button-1’,
number: 1,
color: ‘red’
},
{
id: ‘btn2’,
name: ‘button-2’,
number: 2,
color: ‘blue’
},
{
id: ‘btn3’,
name: ‘button-3’,
number: 3,
color: ‘orange’
}
],
current: {}
},
methods: {
setCurrent(btn) {
this.current = btn;
}
}
});
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id=”app”>
<input type=”button” v-for=”btn in buttons” :id=”btn.id” @click=”setCurrent(btn)” :value=”btn.name”>
<p>{ current.id }</p>
<p>{ current.name }</p>
<p>{ current.number }</p>
<p>{ current.color }</p>
</div>

Solution 2:

For Button:

<button id=”btn1” name=”” number=”” color=”” @click=”set_SelectedButton(1)”>One</button>

in Methods:

set_SelectedButton(value){
// or Based on condition how every you want
this.btn_id=”value”
}

<h2>Clicked button data:</h2>

<p>{ button[btn_id].id }</p>
<p>{ button[btn_id].name }</p>
<p>{ button[btn_id].number }</p>
<p>{ button[btn_id].color }</p>

Solution 3:

You just need to create a function based on button number.

<button id=”btn1” name=”” number=”” color=””
@click = “clickedOn(1)”>One</button>
<button id=”btn2” name=”” number=”” color=””
@click = “clickedOn(2)”>Two</button>
<button id=”btn3” name=”” number=”” color=””
@click = “clickedOn(3)”>Three</button>

<hr>
<h2>Clicked button data:</h2>
<p>{ dataToShow.id }</p>
<p>{ dataToShow.name }</p>
<p>{ dataToShow.number }</p>
<p>{ dataToShow.color }</p>
</div>

You can check working example here:
https://jsfiddle.net/nud19tfz/

var app = new Vue({
el: ‘#app’,
data: {
buttons: [
{
id: ‘btn1’,
name: ‘button-1’,
number: 1,
color: ‘red’
},
{
id: ‘btn2’,
name: ‘button-2’,
number: 2,
color: ‘blue’
},
{
id: ‘btn3’,
name: ‘button-3’,
number: 3,
color: ‘orange’
}
],
dataToShow: {}
},
methods: {
clickedOn: function(btnNum) {
this.dataToShow = this.buttons[btnNum-1]
}
}
});

[Vue.js] Is there a specific method in which I have to invoke a vuex action from a vue component?

When I invoke an imported vuex action in my vue.js file the code errors out and breaks the site. I’ve even broken it down to the simplest of things (console log a string from within the action when I click a button tied to that action).

In my vue.js root

import vue.js from ‘vue’
import ‘./plugins/vuetify’
import App from ‘./App.vue’
import router from ‘./router’
import JsonCSV from ‘vue-json-csv’
import { store } from ‘./store/index’

Vue.component(‘downloadCsv’, JsonCSV)
Vue.config.productionTip = false

new Vue({
render: h => h(App),
router,
store
}).$mount(‘#app’)

In my .vue.js file:

import {mapGetters,mapActions} from ‘vuex’

methods: {
…mapActions([
‘sendDraftSelectionPost’
]),
selectPlayerMethod() {
this.sendDraftSelectionPost(‘hello’)
}
}

In my index.js file in which I’ve imported Vuex

import vue.js from ‘vue’
import Vuex from ‘vuex’
import { debug } from ‘util’;
import draft from ‘./modules/draft’

Vue.use(Vuex)
Vue.config.devtools = true

const store = new Vuex.Store({
strict: debug,
modules: {
draft,
}
})

export default store

In my actions.js file:

const actions = {

sendDraftSelectionPost ({ commit }, draftSelection) {
console.log(draftSelection)
}

}

export default actions

The expected results should be I simply see a string console logged in dev console saying ‘Hello’

However, I get a bit nasty error saying the following:
[vue.js warn]: Error in v-on handler: “TypeError: Cannot read property ‘dispatch’ of undefined”

I haven’t even typed the word “dispatch” in my code, so I’m thoroughly confused. After searching on here and finding a lot of posts similar, I haven’t found anything that has a solid answer or solution.

Any help is appreciated.

Solution :

Per conversation with @Phil, the solution to the original problem (not the sub problem stated in the comments) was to fix my import in my root vue.js from import { store } from ‘./store/index’ to import store from ‘./store’. Thanks, @Phil!!!

[Vue.js] Using $emit from child component to send data to the parent component doesn't work with Vue

I’m writing a “tabs” component.

when trying to send data using the sendTabsData() method in my code, and for some reason it’s not working using $emit.

This is my tab component code:

<template>
<div id=”tabs”>
<div id=”tabs-cont”>
<div class=”tabbable-panel”>
<div class=”tabbable-line”>
<ul class=”nav nav-tabs” role=”tablist”>
</ul>
<div class=”tab-content”>
<slot></slot>
</div>
</div>
</div>
</div>
</div>
</template>

<script>
export default {
name: ‘DashboardTabs’,
props: {
tabs: {
type: Object,
required: true,
default: {}
}
},
data() {
return {
displayed: ‘’,
tabName: ‘’,
$tabsContainer: null,
navTabs: null,
tabContent: null
}
},
created() {
},
mounted() {
this.init();
},
watch: {
},
methods: {
init: function() {
// Fetch UI elements
this.$tabsContainer = $(‘#tabs’);
this.navTabs = this.$tabsContainer.find(‘.nav-tabs’);
this.tabContent = this.$tabsContainer.find(‘.tab-content’);

this.createTabs(this.tabs);
},
// Create tabs by result
createTabs: function(tabs) {
if ( this.tabs !== undefined || this.tabs.length > 0 ) {
this.setTabsBtns(tabs);
}
},
//
tabClick: function(e) {
this.changeDisplayNames(e);
this.sendTabsData();
},
// Change display names
changeDisplayNames: function(e) {

let liItem = e[‘target’][‘dataset’][‘displaytable’];

if (liItem) {
// Update variable table name
this.displayed = liItem;
// Remove the ‘$’ and ‘Table’ text
let tableCategory = this.displayed.replace(‘Table’, ‘’);
tableCategory = tableCategory.replace(‘$’, ‘’);
// Update “global” variable of the current table
this.tabName = tableCategory.charAt(0).toUpperCase() + tableCategory.slice(1);
}
},
// Set tabs li btns
setTabsBtns: function(tabs) {

for (let key in tabs) {
this.navTabs.append(`<li class=”nav-item” @click=”this.tabClick”> <a href=”#tab_default_${key}” class=”nav-link” data-toggle=”tab” data-displayTable=”${tabs[key]}”> ${tabs[key]} </a> </li>`);
}

this.navTabs.find(‘li:first a’).addClass(‘active’);
this.displayed = this.tabs[0];
this.tabName = this.tabs[0];
},
// Set tabs content divs - not relevant if you don’t want to load extra data to the DOM
setTabsContent: function(tabs) {

for (let key in tabs) {
this.tabContent.append(`<div class=”tab-pane” id=”tab_default_${key}”> <table class=”aTable hover display” id=”${tabs[key]}”> </table> </div>`);
}

this.tabContent.find(‘.tab-pane’).first().addClass(‘active’);
},
hideTabs: function() {
this.$tabsContainer.slideUp(‘slow’);
},
showTabs: function() {
this.$tabsContainer.slideDown(‘slow’);
},
// Send tab data to parent
sendTabsData: function(){
let data = {
‘tabDisplayed’: this.displayed,
‘tabName’: this.tabName
};
this.$emit(‘tabsData’, data);
}
}
};
</script>

and this is the parent component:

<script>
// import ProgressBar from “../components/ProgressBar.vue”;
// import _ from ‘lodash’;
import DashboardForm from “../components/DashboardForm.vue”;
import DashboardTabs from “../components/DashboardTabs.vue”;

export default {
name: ‘Gsuite’,
components: {
// ProgressBar,
DashboardForm,
DashboardTabs
},
// mixins: [GF],
data() {
return {
};
},
created() {
},
mounted() {
},
destroyed() {
},
watch: {
},
methods: {
// Submit form
formSubmit: function(data) {
console.log(‘Submit form here’);
console.log(data);
},
// Tabs data
fetchTabsData: function(data) {
console.log(‘tab was clicked’);
console.log(data);
}
}
}
</script>

<!– Template –>
<template>

<div id=”gsuite”>

<!– DashboardForm –>
<DashboardForm
:useGroupFilter=”true”
:useDateRange=”true”
@submit=”formSubmit”
/>

<!– Main Data Container –>
<div id=”data-container”>
<div id=”chart-container”></div>
<!– Dashboard Tabs and Tab Container –>
<DashboardTabs
:tabs=”{ 0: ‘potato’, 1: ‘banana’ }”
@tabsData=”fetchTabsData”
\>
<!– Datatable –>
<!– <DashboardDatatable/> –>
</DashboardTabs>

</div>
<!– END data-container –>

</div>
</template>

as you can see, in my parent component, there is a submit emit that fetches data (and works fine).

The only difference between the tabs component and the form component is that the tab component generates the <li>s that have the click event bined to.

So just to be clear with my question:

How do I send data from a child component to a parent component using $emit when in this case - the element that has the click event bind to it (onClick ==> send/listen the data to the parent component) is dynamically self-generated and not “static”.

EDIT:
using v-for doesn’t seem to get the requested result:

<li class=”nav-item” @click=”this.tabClick” v-for=”(tab,index) in tabs”>
<a :href=”`#tab_default_${index}`“ class=”nav-link” data-toggle=”tab” :data-displayTable=”`${tab}`“> ${tab} </a>
</li>

I get the error:

Error in render: “TypeError: Cannot read property ‘tabClick’ of undefined”

Seems like it’s not letting me to add a @click

Edit2:

tryed using @click.native=”this.tabClick” in v-for - doesn’t result any errors but my dummy console.logs do not appear. click event doesn’t run prroperly.

Solution :

the component emit a tabs event (this.$emit(‘tabs’, data)), so, the parent should listen to the tabs event : @tabs=”tabsData” instead of submit

[Vue.js] How to increment based on checkbox and input values

when trying to create a button that will change based on how many checkboxes and input values are entered/selected.

For example, there is a button html that changes based on how many items are selected

Buy (0 items selected)
Buy 1 item (1 item selected/entered)
Buy x items (x items selected/entered)

using a buyCounter data variable set to 0 currently. I would like to increase/decrease this counter based on the checkbox/input values.

If a checkbox is selected, it counts as +1, if deselected -1.

On the input, it takes any value entered and adds its to the counter. For example if 4 is entered on an input, add +4 to the counter.

Currently not focused on if that number is more than the amount allowed, really just trying to figure out the counter part.

I created this example below in codepen to get close enough to what I’m trying to achieve. Any help in the right direction would be greatly appreciated

https://codepen.io/anon/pen/QooWZV?&editable=true&editors=101

TEMPLATE

<div id=”app”>
<v-app id=”inspire”>
<v-data-table
v-model=”selected”
:headers=”headers”
:items=”desserts”
item-key=”name”
class=”elevation-1”
\>
<template v-slot:items=”props”>
<td v-if=”props.item.available > 1” style=”display:inline-flex”>
<v-text-field style=”width:5%; padding-bottom:10px;”></v-text-field> of { props.item.available }
</td>
<td v-else>
<v-checkbox
v-on:change=”increment($event)”
v-model=”props.selected”
primary
hide-details
\></v-checkbox>
</td>
<td>{ props.item.name }</td>
<td class=”text-xs-right”>{ props.item.calories }</td>
<td class=”text-xs-right”>{ props.item.fat }</td>
<td class=”text-xs-right”>{ props.item.carbs }</td>
<td class=”text-xs-right”>{ props.item.protein }</td>
<td class=”text-xs-right”>{ props.item.iron }</td>
</template>
</v-data-table>
<v-layout row wrap class=””>
<v-flex xs4 class=”text-xs-left”>
<v-btn
v-if=”buyCounter < 1”
color=”blue-grey”
class=”white–text”>
Buy
</v-btn>
<v-btn
v-else-if=”buyCounter > 0 && buyCounter < 2”
color=”blue-grey”
class=”white–text”>
Buy { buyCounter } Item
</v-btn>
<v-btn
v-else-if=”buyCounter > 1”
color=”blue-grey”
class=”white–text”>
Buy { buyCounter } Items
</v-btn>
</v-flex>
<v-flex xs4 class=”text-xs-center”>
</v-flex>
<v-flex xs4 class=”text-xs-right”>
</v-flex>
</v-layout>
</v-app>
</div>

SCRIPT

new Vue({
el: ‘#app’,
data () {
return {
selected: [],
buyCounter: 0,
headers: [
{
text: ‘Count’,
align: ‘left’,
sortable: false,
value: ‘’
},
{
text: ‘Dessert (100g serving)’,
align: ‘left’,
sortable: false,
value: ‘name’
},
{ text: ‘Calories’, value: ‘calories’ },
{ text: ‘Fat (g)’, value: ‘fat’ },
{ text: ‘Carbs (g)’, value: ‘carbs’ },
{ text: ‘Protein (g)’, value: ‘protein’ },
{ text: ‘Iron (%)’, value: ‘iron’ }
],
desserts: [
{
name: ‘Frozen Yogurt’,
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: ‘1%’,
available: 1
},
{
name: ‘Ice cream sandwich’,
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: ‘1%’,
available: 2
},
{
name: ‘Eclair’,
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
iron: ‘7%’,
available: 1
},
{
name: ‘Cupcake’,
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
iron: ‘8%’,
available: 1
},
{
name: ‘Gingerbread’,
calories: 356,
fat: 16.0,
carbs: 49,
protein: 3.9,
iron: ‘16%’,
available: 3
},
{
name: ‘Jelly bean’,
calories: 375,
fat: 0.0,
carbs: 94,
protein: 0.0,
iron: ‘0%’,
available: 1
},
{
name: ‘Lollipop’,
calories: 392,
fat: 0.2,
carbs: 98,
protein: 0,
iron: ‘2%’,
available: 2
},
{
name: ‘Honeycomb’,
calories: 408,
fat: 3.2,
carbs: 87,
protein: 6.5,
iron: ‘45%’,
available: 1
},
{
name: ‘Donut’,
calories: 452,
fat: 25.0,
carbs: 51,
protein: 4.9,
iron: ‘22%’,
available: 1
},
{
name: ‘KitKat’,
calories: 518,
fat: 26.0,
carbs: 65,
protein: 7,
iron: ‘6%’,
available: 3
}
]
}
},
methods:{
increment(event){
console.log(this.selected);
const isChecked = event;

if(isChecked){
this.buyCounter++;
}else{
this.buyCounter–;
}

}
}
})

Looking to create a button that recognizes how many items are about to be bought.

Solution :

I don’t think what you want to do should be done like that, but in order to answer the question, I’d use a computed property in order to calculate the buyCounter based on each value.

The computed property may look something like this

computed: {
buyCounter() {
return this.desserts.reduce((sum, item) => sum += parseInt(item.value), 0)
}
},

Notice you need to start setting a value on each dessert item, and passing it to the v-models
Working example: https://codepen.io/anon/pen/ZPPGwx?editors=1010

[Vue.js] Vue method called when clicking on component element

Strange behavior, there is function called sum.
This functions should be called once (after getting data from the server, and it’s what happening)
but then it’s getting called every time I click on other elements in the component…it could be even select element or date selector…everything that have v-model defined (I think)

What I’m missing here?

Thanks!

<td><span>{_sum(‘device’)}</span></td>

** important : this td element is not defined inside loop.

Solution :

Ok, got it…the solution is to attach the main object
(the one who responsible for the table data) to a watch property.
Now only when the table items getting an update the function will execute.

[Vue.js] Element UI $confirm is not a function

I’m getting Error in v-on handler: “TypeError: this.$confirm is not a function when calling Element UI’s this.$confirm from Vue:

Maybe I’m not importing something that I should (docs and examples suggest that no additional imports are required)?

I’m trying to build a vue.js app using Element UI. It has a table with a delete button in each row. The click handler calls this.$confirm to show a confirmation dialog for the user. It is not quite clear to me from Element documentation, but seems like Element extends vue.js components with $confirm out of the box.

Template:

<el-table-column label=”” width=”180”>
<template slot-scope=”scope”>
<el-button circle type=”danger” @click=”beginRemove(scope.row)”>
X
</el-button>
</template>
</el-table-column>

Script:

<script>
import * as API from ‘../../services/data.js’
import { ElementUI, MessageBox } from ‘element-ui’; // ???
export default {

methods: {
beginRemove(item) {
this.$confirm(`Do you really want to delete ${ item.fullName } ?`,
‘Confirmation’,
{
confirmButtonText: ‘OK’,
cancelButtonText: ‘Cancel’,
type: ‘warning’
})

}
}
}
</script>

Dependencies (package.json):

“dependencies”: {
“element-ui”: “^2.6.3”,
“lodash”: “^4.17.11”,
“moment”: “^2.24.0”,
“regenerator”: “^0.13.3”,
“vue”: “^2.6.10”,
“vue-moment”: “^4.0.0”
},

I’m bootstrapping vue.js like this:

import vue.js from ‘vue/dist/vue.js’;

import {
ElementUI, // Element is undefined when imported
Table,
TableColumn,
Form,
FormItem,
Input,
Button,
DatePicker,
Row,
Col,
Select,
Option,
Pagination
} from ‘element-ui’
import ‘element-ui/lib/theme-chalk/index.css’;

Vue.use(require(‘vue-moment’));
Vue.use(ElementUI);

Vue.component(Table.name, Table)
Vue.component(TableColumn.name, TableColumn)
Vue.component(Form.name, Form)
Vue.component(FormItem.name, FormItem)
Vue.component(Input.name, Input)
Vue.component(Button.name, Button)
Vue.component(DatePicker.name, DatePicker);
Vue.component(Row.name, Row);
Vue.component(Col.name, Col);
Vue.component(Select.name, Select);
Vue.component(Option.name, Option);
Vue.component(Pagination.name, Pagination);

import * as NewItem from ‘./components/new-item/new-item.vue’;
import * as NamesList from ‘./components/names-list/names-list.vue’;
import * as NamesFilter from ‘./components/names-filter/names-filter.vue’;
import * as FilterableList from ‘./components/filterable-list/filterable-list.vue’;

(The malfunctioning handler lives in the names-list component…)

Solution :

if I import ElementUI I get this TypeError: Cannot read property ‘install’ of undefined

the code incorrectly imports ElementUI as a named import. The element-ui package doesn’t have a named import of ElementUI, so it would be undefined. The default import is what you would use there (but this isn’t what you actually need):

//import { ElementUI } from ‘element-ui’ // DON’T DO THIS
import ElementUI from ‘element-ui’
Vue.use(ElementUI)

Since you’re importing the elements individually (to save on bundle size), you shouldn’t also import ElementUI globally like this, which would defeat the bundle size savings.

It is not quite clear for me from Element documentation, but seems like Element extends vue.js components with $confirm out of the box.

The docs state that the global $confirm method is only available when fully importing Element like this:

import ElementUI from ‘element-ui’
Vue.use(ElementUI)

Given you’re individually importing elements, you should import the confirm method locally in a component instead. That is, import MessageBox for its confirm method:

// MyComponent.vue
import { MessageBox } from ‘element-ui’

export default {
methods: {
handleDelete(row) {
MessageBox.confirm(`Do you really want to delete ${row.name} ?`,
“Confirmation”,
{
confirmButtonText: “OK”,
cancelButtonText: “Cancel”,
type: “warning”
})
}
}
}

demo

[Vue.js] Unable to return the sum of an object array property

when trying to return the sum of an object property from an array.
I managed to get this done in another component, but fail to redo it in another.

I get the following error: this.cartitems.forEach is not a function”

Below is the a working example:

<template>
<div id=”shopcartpreview” v-if=”carthover”>
<div class=”cartitem” v-for=”item in cartitems”>
<div class=”cartitempic”><img class=”productImg” width=”80px”
height=”80px” v-bind:src=”‘assets/products/‘ + item.image”></div>
<div class=”cartitemdetails”>
<div class=”cartitemname”>{item.name}</div>
<div class=”cartitemqty”>{item.qty} X </div>
<div class=”cartitemprice”>{item.unit_price}</div>
</div>
<div class=”cartitemdelete”>
<img src=”assets/images/icon-bin.png” width=”15px”
height=”15px”>
</div>
</div>

<div class=”carttotal”>
<div class=”carttotaltext”>TOTAL:</div>
<div class=”carttotalprice”>{Total}</div>
</div>
<div class=”cartcheckouttbn”>PROCEED TO CHECKOUT</div>
<div class=”viewcart”>VIEW CART</div>

</div>
</template>
<script>
module.exports = {
data: function () {
return{
cartitems: 0,
carthover: false
}
},
created(){
EventBus.$on(‘addToCart’, (payload) =>{
this.cartitems = payload
}),
EventBus.$on(‘mouseover’, (carthover) =>{
this.carthover = carthover
$(‘#shopcartpreview’).css(‘display’,’block’);
})
},
computed: {
Total: function() {
var total = 0;
this.cartitems.forEach(item => {
total += (item.unit_price * item.qty);
});
return total;
}
}
}

below is the code that I can’t get to work properly:

<template>
<div>
<div id=”headerLogo”>{carthover}<span v-if=”carthover”> | {cartitems[0].name}</span></div>
<div id=”headerAction”>
<div class=”headerActionItem”>LOGIN/REGISTER</div>
<div class=”headerActionItem”><img src=”assets/images/icon-search.png” width=”20px” height=”20px”></div>
<div class=”headerActionItem”><img src=”assets/images/icon-settings.png” width=”20px” height=”20px”></div>
<div class=”headerActionItem”><img src=”assets/images/icon-love.png” width=”20px” height=”20px”><a class=”floating ui red circular label”>0</a></div>
<div class=”headerActionItem” @mouseover=”mouseOver”><img src=”assets/images/icon-cart.png” width=”26px” height=”20px”><a class=”floating ui red circular label elProduct” id=”cartLabel”>{Totall}</a></div>
</div>
<shopcart-preview></shopcart-preview>
</div>
</template>

<script>
module.exports = {
data: function () {
return{
cartitems: 0,
carthover: false
}
},
components: {
‘shopcart-preview’: httpVueLoader(‘components/shopcart-preview.vue’)
},
created(){
EventBus.$on(‘addToCart’, (payload) =>{
this.cartitems = payload
})
},
methods: {
mouseOver(){
this.carthover = true
carthover = true
EventBus.$emit(‘mouseover’,carthover);
}
},
computed: {
Totall: function() {
var totall = 0;
this.cartitems.forEach(item => {
totall += (item.unit_price * item.qty);
});
return totall;
}
}
}

The part that isnt working is the following:

computed: {
Totall: function() {
var totall = 0;
this.cartitems.forEach(item => {
totall += (item.unit_price * item.qty);
});
return totall;
}
}

There is a lot of code, but that is to give a full picture of what is happening in code. Perhaps the problem is the result of another part of the code.

Solution :

this.cartitems is not an Array, and therefore doesnt have the Array.forEach() method. This might be because you have set the initial state of cartItems to 0 here

data: function () {
return{
cartitems: 0,
carthover: false
}
},

Keep in mind that even if this.cartItems is later modified to be an array when you assign payload to it, if the forEach call runs before the mutation is done, the script will crash.

[Vue.js] vue-konva make v-text use vars/props

So we have a line which works just fine

<v-text :config=”{text: ‘sampleText’}” />

But how to make v-text element to use vue.js variable/props?

<v-text :config=”{text: {sampleText}}” />

vue.js doesn’t like this:

Errors compiling template:
invalid expression: Unexpected token { in {text: {sampleText}}

What is the right way?

Solution :

You just need to use:

<v-text :config=”{text: sampleText}” />

where sampleText is a vue.js variable

[Vue.js] this.$set sets data only once

when getting difficulties to update data multiple times using this.$set(). It only works for first time and if I try one more time then nothing changes. Object gets updated with new data but changes doesn’t reflect on form.

Here is what there is done so far -

data () {
return {
days : [
{id : 1,day : ‘MONDAY’ ,status : false ,times: [‘’]},
{id : 2,day : ‘TUESDAY’ ,status : false ,times: [‘’]},
{id : 3,day : ‘WEDNESDAY’ ,status : false ,times: [‘’]},
{id : 4,day : ‘THURSDAY’ ,status : false ,times: [‘’]},
{id : 5,day : ‘FRIDAY’ ,status : false ,times: [‘’]},
{id : 6,day : ‘SATURDAY’ ,status : false ,times: [‘’]},
{id : 7,day : ‘SUNDAY’ ,status : false ,times: [‘’]}
],
}
},
methods : {
manageSlotTime(event,parentIndex,childIndex) {
var data = this.days[parentIndex].times;
for(var i=0;i<data.length;i++)
{
if(i == childIndex)
{
if(childIndex == 0)
{
data[i] = {};
data[i].slot_id = ‘’;
data[i].time = event;
data[i].slot_status = false;
}
else{
data[i].time = event;
data[i].slot_status = false;
}

}
}
//Here need to set data.
this.$set(this.days[parentIndex].times, data);
},
}

Any help would be appreciated.
Thanks

Solution :

There are several weird things here.

First, you setup times property for each day as a non-empty array - holding an empty string as a single element. But then each manageSlotTime call either augment an existing element of that array or replace the first one with an object. That replacement seems to be the reason why you see how the first set call kinda works. Hint: it actually doesn’t.

Second, you seem to miss the fact that this line…

var data = this.days[parentIndex].times

… doesn’t create a new array. Instead it creates another reference to the array stored in this.days[parentIndex].times. Afterwards anything you do to data within the loop is actually modifying the array inside the state directly. That, in turn, makes call to $set irrelevant.

Finally, for some reasons you use for to access a property in array by index; it’s, well, just an overcomplication. Ask yourself: if you only do some work inside that if (i === childIndex) check, and all that work is about accessing data[i], why can’t you just do data[childIndex] directly?

The bottom line - looks like the function can be rewritten like this:

manageSlotTime(event, parentIndex, childIndex) {
var timesRef = this.days[parentIndex].times;

var slot = childIndex === 0 ?
{ slot_id: ‘’ } :
Object.assign({}, timesRef[childIndex]);
slot.time = event;
slot.slot_status = false;

this.$set(timesRef, childIndex, slot);
}

There are few questions here (what’s that special about childIndex === 0? how slot_id is assigned?), but this code essentially does the same as yours, but with less lines and proper $set usage.

Solution 2:

This most likely has to do with array Caveats. You initially assign times an array. However, vue.js does not detect changes to arrays.

Due to limitations in JavaScript, vue.js cannot detect direct changes to an array.

If the property is an array, using the following syntax within the loop should help to overcome the problem.

this.$set(vm.items, indexOfItem, newValue)

So in the example you could use the following.

this.$set(this.days[parentIndex].times, i, dataObject);

This would look something like this.

if(childIndex == 0) {
data = {};
data.slot_id = ‘’;
data.time = event;
data.slot_status = false;
this.$set(this.days[parentIndex].times, i, data);
}

[Vue.js] Two checkboxes, either one checked or the other, not both, how in vue.js?

there is two pricing option checkboxes in my jobs board, one is make a job sticky for one week, the other to make a job sticky for one month. How can I implement this using Vue.js? Obviously, one can be clicked OR the other, but not both. Both checkboxes start as unchecked.

Solution :

You should use radio type inputs for that case, using the same “name” attribute for both:

<input type=”radio” id=”week” value=”week” name=”jobPostingLength” v-model=”jobPostingLength”>
<label for=”week”>1 Week</label>

<input type=”radio” id=”month” value=”month” name=”jobPostingLength” v-model=”jobPostingLength”>
<label for=”month”>1 Month</label>