link2466 link2467 link2468 link2469 link2470 link2471 link2472 link2473 link2474 link2475 link2476 link2477 link2478 link2479 link2480 link2481 link2482 link2483 link2484 link2485 link2486 link2487 link2488 link2489 link2490 link2491 link2492 link2493 link2494 link2495 link2496 link2497 link2498 link2499 link2500 link2501 link2502 link2503 link2504 link2505 link2506 link2507 link2508 link2509 link2510 link2511 link2512 link2513 link2514 link2515 link2516 link2517 link2518 link2519 link2520 link2521 link2522 link2523 link2524 link2525 link2526 link2527 link2528 link2529 link2530 link2531 link2532 link2533 link2534 link2535 link2536 link2537 link2538 link2539 link2540 link2541 link2542 link2543 link2544 link2545 link2546 link2547 link2548 link2549 link2550 link2551 link2552 link2553 link2554 link2555 link2556 link2557 link2558 link2559 link2560 link2561 link2562 link2563 link2564 link2565 link2566 link2567 link2568 link2569 link2570 link2571 link2572 link2573 link2574 link2575 link2576 link2577 link2578 link2579 link2580 link2581 link2582 link2583 link2584 link2585 link2586 link2587 link2588 link2589 link2590 link2591 link2592 link2593 link2594 link2595 link2596 link2597 link2598 link2599 link2600 link2601 link2602

[Vue.js] Uncaught TypeError Cannot read property '$router' of undefined

when working on a firebase based vue.js app that should redirect users to home page after successfully logged in. I receive howewer Cannot read property ‘$router’ of undefined error in the console once clicked on login.

I already tried to import router from “./router” on Login component but it didn’t work.

main.js

import vue.js from “vue”;
import firebase from “firebase”;
import App from “./App.vue”;
import router from “./router”;
import swalPlugin from ‘./plugins/VueSweetalert2’;

Vue.config.productionTip = false;

let app =’’;

firebase.initializeApp( {
apiKey: “xx”,
authDomain: “xx”,
databaseURL: “xx”,
projectId: “xx”,
storageBucket: “xx”,
messagingSenderId: “xx”
});

Vue.use(swalPlugin);

firebase.auth().onAuthStateChanged(() => {
if (!app) {
app = new Vue({
router,
render: h => h(App)
}).$mount(“#app”);
}
});

router.js

import firebase from ‘firebase’;
import vue.js from “vue”;
import Router from “vue-router”;
import Home from “./views/Home.vue”;
import Login from “./views/Login.vue”;
import SignUp from “./views/SignUp.vue”;

Vue.use(Router);

const router = new Router({
routes: [
{
path: “*“,
redirect: “/login”,
},
{
path: “/“,
redirect: “/login”,
},
{
path: ‘/login’,
name: ‘Login’,
component: Login
},
{
path: ‘/sign-up’,
name: ‘SignUp’,
component: SignUp
},
{
path: “/home”,
name: “Home”,
component: Home,
meta: {
requiresAuth: true
}
}
]
});

router.beforeEach ((to, from, next) => {
const currentUser = firebase.auth.currentUser;
const requiresAuth = to.matched.some (record => record.meta.requiresAuth);

if (requiresAuth && !currentUser) next(‘login’);
else if (!requiresAuth && currentUser) next(‘home’);
else next();

});

export default router;

Login.vue

<template>
<form autocomplete=”off”>
<div class=”login”>
<h1>Login</h1>
<p>Sign in to stay updated with the latest news</p>
<hr>

<input type=”text” placeholder=”Email” v-model=”email”>

<input type=”password” placeholder=”Enter Password” v-model=”password”>

<hr>
<button @click=”login”>Login</button>
<p>Don’t have an account yet? Create one <router-link to=”/sign-up”>here</router-link></p>

</div>
</form>
</template>

<script>
import firebase from ‘firebase’;
import Swal from ‘sweetalert2’;

export default {
name: ‘login’,
data() {
return {
email: ‘’,
password: ‘’
}
},
methods: {
login: function(){
firebase.auth().signInWithEmailAndPassword(this.email, this.password).then(
function (user) {
this.$router.replace(‘home’)
},
function (err) {
Swal.fire({
type: ‘error’,
title: ‘An error occurred…’,
text: err.message
})
}
);
}
}
}
</script>

Solution :

I think you lost the scope using function.

Solve it by using es6 syntax (if you can afford/using babel), (user) => { .. }.

Or by setting something like var _this = this; in the main login function and referencing that.

[Vue.js] Cypress tests continuously run XHR posts when visiting localhost (running vue.js)

I’m relatively new to cypress, however, whenever I run cy.visit on localhost the XHR requests continuously run. This does not happen if when visiting a remote URL. Here’s the code:

describe(‘Applicant Login’, () => {
it(‘focuses input on login box’, () => {
cy.visit(‘http://localhost:3000/login')
})
})

Cypress continually runs XHR requests over and over until I stop. I’m running a vue.js app via nuxt.js. Here’s the log output:

there is no errors, no request or response info, the continuous requests.

Thanks for the help!

Solution :

Many thanks to Kondasamy Jayaraman. The request is coming from a logrocket plugin trying to reach its service. I hadn’t noticed it in the network tab when using the application.
Much appreciation.

[Vue.js] How to pass the data with dynamic key in semantic UI vue dropdown?

when facing an issue with semantic-ui-vue.js dropdown.

Here is my sandbox link: https://codesandbox.io/s/3qknm52pm5.

In my sandbox, there is two dropdowns: From and To.

From shows the correct values and To doesn’t due to key mismatch.

My App.vue.js contain this script

<script>
export default {
data() {
return {
from: [],
to: [],
fromCollection: [
{
value: “abc@gmail.com“,
text: “abc@gmail.com
},
{
value: “def@gmail.com“,
text: “def@gmail.com
},
{
value: “qwerty@gmail.com“,
text: “qwerty@gmail.com
},
{
value: “shubham@gmail.com“,
text: “shubham@gmail.com
}
],
toCollection: [
{
email: “abc@gmail.com
},
{
email: “def@gmail.com
},
{
email: “qwerty@gmail.com
},
{
email: “shubham@gmail.com
}
]
};
}
};
</script>

and the component I used for both of them are

<sui-dropdown
fluid
multiple
:options=”fromCollection”
placeholder=”from”
selection
v-model=”from”
search
:allowAdditions=”true”
text=”email”
/>
<sui-dropdown
fluid
multiple
:options=”toCollection”
placeholder=”from”
selection
v-model=”to”
search
:allowAdditions=”true”
text=”email”
/>

The 1st dropdown shows the correct values because there is passed the data from fromCollection whereas the 2nd dropdown doesn’t show any text because there is passed the data from toCollection which has different key names.

Can someone help me to pass the data with dynamic keys like toCollection?

I couldn’t find anything related in the documentation.
Can someone help?

Solution :

there is no way to define field name for dropdown

only use computed to regenerate new array for it

demo

[Vue.js] How to setup multiple keys for components in template tag using v-for?

I wanted to render a list using v-for. It’s simple enough, the documentation explains almost every use case. it to look like that:

<template v-for=”(item, index) in items” :key=”index”>
<CustomComponent :item=”item”/>
<Separator v-if=”index !== items.length-1”/>
</template>

Unfortunately, the documentation does not say how to set a key for multiple custom components in one v-for.

Obviously, I don’t want to include separator to my custom component, because it is used in other places too. Code there is pasted is generating those errors:
‘template’ cannot be keyed. Place the key on real elements instead.
I can set a key on component and separator using an index but I got errors: Duplicate keys detected: ‘x’. This may cause an update error.

For now, I’m doing it like that but it’s an ugly hack and would not work with more components in one template.

<template v-for=”(item, index) in items”>
<CustomComponent :item=”item” :key=”(index+1)*-1”/>
<Separator v-if=”index !== items.length-1” :key=”(index+1)”/>
</template>

Example from documentation explains templates on the list with basic components which does not require keys.
Does anyone know how should I do it correctly?

Ps. It is not recommended to use v-if on v-for. Could someone suggest how to change my code not to use v-if but don’t render separator under the last element?

Solution :

Here is how I was able to generate a key — you could customize the generateKey method to return whatever you like.

<template>
<div>
<div
v-for=”(item, index) in items”
:key=”generateKey(item, index)”
\>Item { index } : { item }</div>
</div>
</template>

<script>
export default {
data() {
return {
items: [“Sun”, “Moon”, “Stars”, “Sky”]
};
},
methods: {
generateKey(item, index) {
const uniqueKey = `${item}-${index}`;
return uniqueKey;
}
}
};
</script>

Working Example: https://codesandbox.io/s/30ojo1683p

[Vue.js] Hide and show a div inside vue.js template for selected item only?

there is an array of songs and inside the template there is an icon to toggle between show/hide of a div. It works when clicked and it expands the div but it expands the div for every item in the array (no matter which song is clicked). I would like it to only expand the div of the clicked item. Do I need to link it the id variable somehow? Here is the code:

This is in the html template:

<div class=”dropdown-icon” title=”Show/Hide Description”
@click=”toggleShowDescription”>
<i class=”icon ion-ios-arrow-dropdown-circle”></i>
</div>

<div :class=”showDescription?’show’:’hide’” v-if=”showDescription”>
<p class=”song-description”>{song.description}</p>

This what there is in the JS concerning the hide/show div element:

songs: [

{
id: 1,
title: “Track 1”,
description: “Description 1”,
url: “”,
keywords:””,
genre:””,
moods:””,
tempo:””,
theme:””,
},

{
id: 2,
title: “Track 2”,
description: “Description 2”,
url:””,
keywords: “”,
genre:””,
moods:””,
tempo:””,
theme:””,
},
],

showDescription: false,
},

methods: {

toggleShowDescription() {
this.showDescription = !this.showDescription;
},

},

Solution :

You are using the value of showDescription for every single song. The best bet would be to create an array that tracks which song descriptions are showing and then add/remove items as the toggle button is clicked.

For the template…

<div class=”dropdown-icon” title=”Show/Hide Description”
@click=”toggleShowDescription(song)”>
<i class=”icon ion-ios-arrow-dropdown-circle”></i>
</div>

<div :class=”showDescription?’show’:’hide’” v-
if=”songsDisplayingDescription.indexOf(song.id) !== -1”>
<p class=”song-description”>{song.description}</p>

and then the script…

songsDisplayingDescription: [],
},
methods: {
toggleShowDescription(song) {
const songId = song.id;
const indexOfSongId = this.songsDisplayingDescription.indexOf(songId);

if (indexOfSongId !== -1) {
this.songsDisplayingDescription.splice(indexOfSongId, 1);
return;
}

this.songsDisplayingDescription.push(songId);
}
}

[Vue.js] How to programmatically add a dynamic style to an element created with createElement in Vue

there is a programmatically created canvas element, and to attach a reactive style to it.

canvas = document.createElement(‘canvas’)

//Add style

this.$refs.parentElement.appendChild(canvas)

Normally you would do it in a template with v-for and v-bind, but I can’t do that in my case. Example:

<canvas :style=”[someReactiveData ? { ‘display’: ‘block’ } : {}]“/>

How would you go about this?

Solution :

I don’t know if this is the best answer, but what I did was:

document.getElementById(“elementId”).style.display = this.style.display

So I just update the style object and you can work with it the way you want, everytime you update the style property, the elementId style will update too.

If I wasn’t clear enough I can reformulate my explanation.

[Vue.js] vuejs typescript and child components Avoid mutating a prop directly

I’m going round in circles here.

there is a vuejs2 app up and running with typescript but hitting an error when i try to pass data to a child component that originates from the store.

<template>
<div>
<form-error :error422.sync=”errors”></form-error>
</div>
</template>

<script lang=”ts”>
import { Component, vue.js } from ‘vue-property-decorator’;
import FormError from ‘@/components/FormError422.vue’;
import cloneObj from ‘@/utils/cloneObj’;

@Component({
components: {
FormError,
},
})
export default class RegisterForm extends vue.js {
get errors() {
return cloneObj(AuthenticationModule.errorRegister);
}
</script>

The child

<template>
<div>
{error422.errors}
</div>
</template>

<script lang=”ts”>
import { Component, Prop, vue.js } from ‘vue-property-decorator’;
import { Generic422 } from ‘@/ms-authentication’

@Component
export default class FormError422 extends vue.js {
@Prop() private error422: Generic422 = {
errors: [],
};
}
</script>

But whatever i do it throws a warning:

[vue.js warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “error422”

Solution :

I think you’re trying to set error422 default value as:

errors: [],

And you’re setting it up directly in the FormError422 class, via the = assignment.

This is not the way you should be using the @Prop() decorator to set up a default value. Instead, you are directly mutating the prop instead of setting up the default value.

therefore, vue.js warns you because you should not do that.

To set up a prop default value with the @Prop decorator, do this:

@Prop({default: {errors: []}) private error422!: Generic422;

[Vue.js] How to update the chart dynamically with vue-chartjs?

I’m using vue.js and vue-chartjs for the first time.
In the simplified code example to add a label to the chart by pressing the add Label button, but the chart is not updating. My code is based on this tutorial.

I tried calling the render method from the child component, but that does not work.

I expected that when I click the add Label button that the label 13 will be added to the chart.

Solution :

You have a few mistakes in the code. First if you want to call a method from child component you have to use special attribute ref. Please see more about ref.

So in the code it should be:

<template>

<chart ref=’chart’ :chart-data=”datacollection”></chart>

</template>

<script>

this.$refs.chart.render() // Not Chart.render()

</script>

Second you have a typo in the Chart.js:

this.chartData // Not this.chartdata

So this means yours render method in mounted is not working and unnecessary. the chart is already drawn by reactiveProp after you set chartData prop.

But unfortunately this:

this.datacollection.labels.push(13);

still not work. If you looking at the source code here you will see the library use watcher on chartData only. It means if you change entire of chartData this will work fine (as it works at first drawn). Please see more about watcher.

So if you want to rely on reactiveProp then when you want update labels you should set:

this.datacollection = {
…this.datacollection,
labels: this.datacollection.labels.concat(13) // avoid to mutate data
}

[Vue.js] watch changes in html element using vue

I’m trying to watch HTML element in the followiing way:

computed: {
content(){
return document.querySelector(“.tab-content”)
}
},
watch: {
content(newVal) {
return newVal;
}
}

but when .tab-content changes (it’s innerHTML) , vue.js wont track/respond to that. any idea why?

Solution :

You can’t watch computed values, the computed methods are already like watchers that are updated when the content changes. You use watch methods to watch for changes in data or props

export default {
data: () => ({
content: ‘’
}),
watch: {
content () {
return this.content
}
}
}

[Vue.js] How to display multiple select options in Sweetalert2 with VueJS?

to configure Sweetalert2 modal in such a way in which when able to select different options from a list. This was easily achieved using the following code:

swal({
title: ‘Select Outage Tier’,
input: ‘select’,
inputOptions: {
‘1’: ‘Tier 1’,
‘2’: ‘Tier 2’,
‘3’: ‘Tier 3’
},
inputPlaceholder: ‘required’,
showCancelButton: true,
inputValidator: function (value) {
return new Promise(function (resolve, reject) {
if (value !== ‘’) {
resolve();
} else {
reject(‘You need to select a Tier’);
}
});
}
}).then(function (result) {
if (result.value) {
swal({
type: ‘success’,
html: ‘You selected: ‘ + result.value
});
}
});

It was copied from a different question and it worked like a charm for the first part of my project. I can add new options in the inputOptions: {} tag. However, to display the options dynamically without having to change the code manually every time add/remove one.

when retrieving the options from a database, by calling an API. This part was also done quickly and it works pretty well. I retrieve the data and store in a variable options: ‘’. The data is stored and ready to be used with the above code.

HERE COMES THE PROBLEM: when still pretty new to VueJS and all I can do for now is basic coding. I tried to use a code snippet, from my own project, inside the inputOptions: {} tag, hoping it will work in the same way it works inside a method:

inputOptions: {
this.options.forEach((option) => {
option.id : option:name
});
},

However, it doesn’t work at all. I get an error Uncaught SyntaxError: Unexpected token . on the second line of the snippet code above.

All to do is to retrieve and display the options, from the database, inside the Sweetalert2 modal. Is there an easier, more efficient way to do so?

Solution :

You can use computed property to prepare data for inputOptions

computed: {
optionsDict() {
if (!this.options) return {}
return this.options.reduce((a, c) => {
a[c.id] = c.name
return a
}, {})
}
}

and then

swal({

inputOptions: this.optionsDict

})