link1781 link1782 link1783 link1784 link1785 link1786 link1787 link1788 link1789 link1790 link1791 link1792 link1793 link1794 link1795 link1796 link1797 link1798 link1799 link1800 link1801 link1802 link1803 link1804 link1805 link1806 link1807 link1808 link1809 link1810 link1811 link1812 link1813 link1814 link1815 link1816 link1817 link1818 link1819 link1820 link1821 link1822 link1823 link1824 link1825 link1826 link1827 link1828 link1829 link1830 link1831 link1832 link1833 link1834 link1835 link1836 link1837 link1838 link1839 link1840 link1841 link1842 link1843 link1844 link1845 link1846 link1847 link1848 link1849 link1850 link1851 link1852 link1853 link1854 link1855 link1856 link1857 link1858 link1859 link1860 link1861 link1862 link1863 link1864 link1865 link1866 link1867 link1868 link1869 link1870 link1871 link1872 link1873 link1874 link1875 link1876 link1877 link1878 link1879 link1880 link1881 link1882 link1883 link1884 link1885 link1886 link1887 link1888 link1889 link1890 link1891 link1892 link1893 link1894 link1895 link1896 link1897 link1898 link1899 link1900 link1901 link1902 link1903 link1904 link1905 link1906 link1907 link1908 link1909 link1910 link1911 link1912 link1913 link1914 link1915 link1916 link1917

[Vue.js] Can you force Vue.js to reload/re-render?Why?

Just a quick question.

Can you force Vue.js to reload/recalculate everything? If so, how?

Solution :

Try this magic spell:

vm.$forceUpdate();

No need to create any hanging vars :)

Update: I found this solution when I only started working with VueJS. However further exploration proved this approach as a crutch. As far as I recall, in a while I got rid of it simply putting all the properties that failed to refresh automatically (mostly nested ones) into computed properties.

More info here: https://vuejs.org/v2/guide/computed.html

Solution 2:

This seems like a pretty clean solution from matthiasg on this issue:

you can also use :key=”someVariableUnderYourControl” and change the key when you want to component to be completely rebuilt

For my use case, I was feeding a Vuex getter into a component as a prop. Somehow Vuex would fetch the data but the reactivity wouldn’t reliably kick in to rerender the component. In my case, setting the component key to some attribute on the prop guaranteed a refresh when the getters (and the attribute) finally resolved.

Solution 3:

Use vm.$set(‘varName’, value). Look for details into Change_Detection_Caveats.

Solution 4:

Why?

…do you need to force an update?

Perhaps you are not exploring vue.js at its best:

To have vue.js automatically react to value changes, the objects must be initially declared in data. Or, if not, they must be added using Vue.set().

See comments in the demo below. Or open the same demo in a JSFiddle here.

new Vue({
el: ‘#app’,
data: {
person: {
name: ‘Edson’
}
},
methods: {
changeName() {
// because name is declared in data, whenever it
// changes, vue.js automatically updates
this.person.name = ‘Arantes’;
},
changeNickname() {
// because nickname is NOT declared in data, when it
// changes, vue.js will NOT automatically update
this.person.nickname = ‘Pele’;
// although if anything else updates, this change will be seen
},
changeNicknameProperly() {
// when some property is NOT INITIALLY declared in data, the correct way
// to add it is using Vue.set or this.$set
Vue.set(this.person, ‘address’, ‘123th avenue.’);

// subsequent changes can be done directly now and it will auto update
this.person.address = ‘345th avenue.’;
}
}
})
/* CSS just for the demo, it is not necessary at all! */
span:nth-of-type(1),button:nth-of-type(1) { color: blue; }
span:nth-of-type(2),button:nth-of-type(2) { color: red; }
span:nth-of-type(3),button:nth-of-type(3) { color: green; }
span { font-family: monospace }
<script src=”https://unpkg.com/vue"></script>

<div id=”app”>
<span>person.name: { person.name }</span><br>
<span>person.nickname: { person.nickname }</span><br>
<span>person.address: { person.address }</span><br>
<br>
<button @click=”changeName”>this.person.name = ‘Arantes’; (will auto update because `name` was in `data`)</button><br>
<button @click=”changeNickname”>this.person.nickname = ‘Pele’; (will NOT auto update because `nickname` was not in `data`)</button><br>
<button @click=”changeNicknameProperly”>Vue.set(this.person, ‘address’, ‘99th st.’); (WILL auto update even though `address` was not in `data`)</button>
<br>
<br>
For more info, read the comments in the code. Or check the docs on <b>Reactivity</b> (link below).
</div>

To master this part of Vue, check the Official Docs on Reactivity - Change Detection Caveats. It is a must read!

Solution 5:

Try to use this.$router.go(0); to manually reload the current page.

Solution 6:

Sure .. you can simply use the key attribute to force re-render (recreation) at any time.

<mycomponent :key=”somevalueunderyourcontrol”></mycomponent>

See https://jsfiddle.net/mgoetzke/epqy1xgf/ for an example

It was also discussed here: https://github.com/vuejs/Discussion/issues/356#issuecomment-336060875

Solution 7:

using v-if directive

<div v-if=”trulyvalue”>
<component-here />
</div>

So simply by changing the value of trulyvalue from false to true will cause the component between the div to rerender again

Solution 8:

I found a way. It’s a bit hacky but works.

vm.$set(“x”,0);
vm.$delete(“x”);

Where vm is the view-model object, and x is a non-existent variable.

Vue.js will complain about this in the console log but it does trigger a refresh for all data. Tested with version 1.0.26.

Solution 9:

Please read this
http://michaelnthiessen.com/force-re-render/

The horrible way: reloading the entire page
The terrible way: using the v-if hack
The better way: using Vues built-in forceUpdate method
The best way: key-changing on the component

<template>
<component-to-re-render :key=”componentKey” />
</template>

<script>
export default {
data() {
return {
componentKey: 0,
};
},
methods: {
forceRerender() {
this.componentKey += 1;
}
}
}
</script>

I also use watch: in some situations.

[Vue.js] vuejs set a radio button checked if statement is true

when trying to make a radio button checked using vuejs v-for only if my if-statement is true. Is there a way to use vuejs’ v-if/v-else for this type of problem?

in php and html I can achieve this by doing the following:

<input type=”radio” <? if(portal.id == currentPortalId) ? ‘checked=”checked”‘ : ‘’?>>

Below is what there is so far using vuejs:

<div v-for=”portal in portals”>
<input type=”radio” id=”{portal.id}” name=”portalSelect”
v-bind:value=”{id: portal.id, name: portal.name}”
v-model=”newPortalSelect”
v-on:change=”showSellers”
v-if=”{portal.id == currentPortalId}”
checked=”checked”>
<label for=”{portal.id}”>{portal.name}</label>
</div>

I know the v-if statement here is for checking whether to show or hide the input.

Any help would be very much appreciated.

Solution :

You could bind the checked attribute like this:

<div v-for=”portal in portals”>
<input type=”radio”
id=”{portal.id}”
name=”portalSelect”
v-bind:value=”{id: portal.id, name: portal.name}”
v-model=”newPortalSelect”
v-on:change=”showSellers”
:checked=”portal.id == currentPortalId”>

<label for=”{portal.id}”>{portal.name}</label>
</div>

Simple example: https://jsfiddle.net/b4k6tpj9/

Solution 2:

I would like to point out a few options when dealing with radios and vue.js. In general if you need to dynamically bind an attribute value you can use the shorthand binding syntax to bind to and calculate that value. You can bind to data, a computed value or a method and a combination of all three.

new Vue({
el: ‘#demo’,
data() {
return {
checkedData: false,
checkedGroupVModel: “radioVModel3”, //some defaul
toggleChecked: false,
recalculateComputed: null
};
},
computed: {
amIChecked() {
let isEven = false;
if (this.recalculateComputed) {
let timeMills = new Date().getMilliseconds();
isEven = timeMills % 2 === 0;
}
return isEven;
}
},
methods: {
onToggle() {
this.toggleChecked = !this.toggleChecked;
return this.toggleChecked;
},
mutateComputedDependentData() {
this.recalculateComputed = {};
}
}
})
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id=”demo”>
<div>
<div>
<span>Simple Radio Group - Only one checked at a time. Bound to data.checkedData</span><br>
<label>Radio 1 - inverse of checkedData = {!checkedData}
<input type=”radio” name=”group1” value=”radio1” :checked=”!checkedData”>
</label><br>
<label>Radio 2 - checkedData = {checkedData}
<input type=”radio” name=”group1” value=”radio2” :checked=”checkedData”>
</label><br>
<span>Understanding checked attribute: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-checked</span>
</div>
<br>
<div>
<span>Simple Radio - Checked bouned to semi-random computed object</span><br>
<label>Radio 1: {amIChecked}
<input type=”radio” :checked=”amIChecked”>
</label>  
<label>Recalculate Computed Value
<button type=”button” @click=”mutateComputedDependentData”>Click Me Several Times</button>
</label>
</div>
<br>
<div>
<span>Simple Radio Group - v-model bound value = {checkedGroupVModel}</span><br>
<label>Simple Radio 1:
<input type=”radio” name=”vModelGroup” value=”radioVModel1” v-model=”checkedGroupVModel”>
</label><br>
<label>Simple Radio 2:
<input type=”radio” name=”vModelGroup” value=”radioVModel2” v-model=”checkedGroupVModel”>
</label><br>
<label>Simple Radio 3:
<input type=”radio” name=”vModelGroup” value=”radioVModel3” v-model=”checkedGroupVModel”>
</label>
</div>
<br>
<div>
<span>Simpe Radio - click handler to toggle data bound to :checked to toggle selection</span><br>
<label>Toggle Radio = {toggleChecked}
<input type=”radio” :checked=”toggleChecked” @click=’onToggle()’>
</label>
</div>
</div>
</div>

[Vue.js] VueJS right way to edit prop without changing parent data

In my parent vue.js component there is a user object.

If I pass that user object to a child component as a prop:

<child :user=”user”></child>

and in my child component I update user.name, it will get updated in the parent as well.

to edit the user object in child component without the changes being reflected in the user object that is in parent component.

Is there a better way to achieve this than cloning the object with: JSON.parse(JSON.stringify(obj))?

Solution :

You don’t have to use the JSON object.

const child = {
props:[“user”],
data(){
return {
localUser: Object.assign({}, this.user)
}
}
}

Use localUser (or whatever you want to call it) inside the child.

Edit

I had modified a fiddle created for another answer to this question to demonstrate the above concept and @user3743266 asked

I’m coming to grips with this myself, and I’m finding this very
useful. the example works well. In the child, you’ve created an
element in data that takes a copy of the prop, and the child works
with the copy. Interesting and useful, but… it’s not clear to me
when the local copy gets updated if something else modifies the
parent. I modified the fiddle, removing the v-ifs so everything is
visible, and duplicating the edit component. If you modify name in one
component, the other is orphaned and gets no changes?

The current component looks like this:

Vue.component(‘edit-user’, {
template: `
<div>
<input type=”text” v-model=”localUser.name”>
<button @click=”$emit(‘save’, localUser)”>Save</button>
<button @click=”$emit(‘cancel’)”>Cancel</button>
</div>
`,
props: [‘user’],
data() {
return {
localUser: Object.assign({}, this.user)
}
}
})

Because I made the design decision to use a local copy of the user, @user3743266 is correct, the component is not automatically updated. The property user is updated, but localUser is not. In this case, if you wanted to automatically update local data whenever the property changed, you would need a watcher.

Vue.component(‘edit-user’, {
template: `
<div>
<input type=”text” v-model=”localUser.name”>
<button @click=”$emit(‘save’, localUser)”>Save</button>
<button @click=”$emit(‘cancel’)”>Cancel</button>
</div>
`,
props: [‘user’],
data() {
return {
localUser: Object.assign({}, this.user)
}
},
watch:{
user(newUser){
this.localUser = Object.assign({}, newUser)
}
}
})

Here is the updated fiddle.

This allows you full control over when/if the local data is updated or emitted. For example, you might want to check a condition before updating the local state.

watch:{
user(newUser){
if (condition)
this.localUser = Object.assign({}, newUser)
}
}

As I said elsewhere, there are times when you might want to take advantage of objects properties being mutable, but there are also times like this where you might want more control.

Solution 2:

you can have a data variable just with the information you want to be locally editable and load the value in the created method

data() {
return { localUserData: {name: ‘’, (…)}
}
(…)
created() {
this.localUserData.name = this.user.name;
}

This way you keep it clear of which data you are editing. Depending on the need, you may want to have a watcher to update the localData in case the user prop changes.

Solution 3:

According to this, children “can’t” and “shouldn’t” modify the data of their parents. But here you can see that if a parent passes some reactive data as a property to a child, it’s pass-by-reference and the parent sees the child’s changes. This is probably what you want most of the time, no? You’re only modifying the data the parent has explicitly shared. If you want the child to have an independent copy of user, you could maybe do this with JSON.parse(JSON.stringify()) but beware you’ll be serializing Vue-injected properties. When would you do it? Remember props are reactive, so the parent could send down a new user at any time, wiping out local changes?

Perhaps you need to tell us more about why you want the child to have it’s own copy? What is the child going to do with its copy? If the child’s user is derived from the parent user in some systematic way (uppercasing all text or something), have a look at computed properties.

[Vue.js] Vue.js and jQuery?

Is it possible to use jQuery with Vue.js? there is a function this function that to use in my vue.js component. The function basically slides the items in and out, but when I implemented using the <script> tags I got a list with all the items instead of the jQuery code working.

$(“#slideshow > div:gt(0)”).hide();

setInterval(function() {
$(‘#slideshow > div:first’)
.fadeOut(0)
.next()
.fadeIn(1000)
.end()
.appendTo(‘#slideshow’);
}, 5000);

How do I use that function in my code?

<template>
<div class=”timer”>
<div class=”title-block”>
<p class=”title”>MG de Jong</p>
<p class=”description”>Sprint 1</p>
</div>
<div class=”column”>
<div class=”block”>
<p class=”digit”>{ days | two_digits }</p>
<p class=”text”>Days</p>
</div>
<div class=”block”>
<p class=”digit”>{ hours | two_digits }</p>
<p class=”text”>Hours</p>
</div>
<div class=”block”>
<p class=”digit”>{ minutes | two_digits }</p>
<p class=”text”>Minutes</p>
</div>
</div>
</div>
</template>
<script>

export default {
props: {
date: {
type: Number
},
},
data() {
return {
now: Math.trunc((new Date()).getTime() / 1000)
}
},
mounted() {
window.setInterval(() => {
this.now = Math.trunc((new Date()).getTime() / 1000);
},1000);

},
computed: {
seconds() {
return (this.modifiedDate - this.now) % 60;
},
minutes() {
return Math.trunc((this.modifiedDate - this.now) / 60) % 60;
},
hours() {
return Math.trunc((this.modifiedDate - this.now) / 60 / 60) % 24;
},
days() {
return Math.trunc((this.modifiedDate - this.now) / 60 / 60 / 24);
},
modifiedDate: function(){
return Math.trunc(Date.parse(this.date) / 1000)
}
},
}
</script>

Solution :

You can do that, but in most of cases, you don’t need to.

If you are learning Vue, then try to think in vue.js and just put jQuery away. In jQuery, you do things in imperative way; but now you should think in declarative way.
Do not manipulate the DOM by yourself directly. All the DOM manipulations should be handled by Vue, you just tell vue.js what you want.

vue.js provides Transition, the requirement can be done by this without jQuery at all. At first you may think it’s not straightforward and want to solve it by jQuery, but once you get the point you will fall in love with it.

Solution 2:

As some of he comments mention, you could use a mounted function. For more details you can see this article: https://vuejsdevelopers.com/2017/05/20/vue-js-safely-jquery-plugin/

Here is a basic example using cleave.js:

<template>
<input />
</template>

<script>
/* eslint-disable no-new */
import Cleave from ‘cleave.js’

export default {
mounted () {
new Cleave(this.$el, {
date: true,
datePattern: [‘d’, ‘m’, ‘Y’]
})

this.$el.oninput = (e) => {
console.log(‘oninput the field’, e.target.value)
this.$emit(‘oninput’, e.target.value)
}
}
}
</script>

<style>

</style>

App.vue

<template>
<div id=”app”>
<smart-cleave @oninput=”logIt”></smart-cleave>
<div>{date}</div>
</div>
</template>

<script>

/* eslint-disable no-new */
import Cleave from ‘cleave.js’
import SmartCleave from ‘./components/SmartCleave’

new Cleave(‘#plain-input’, {
date: true,
datePattern: [‘d’, ‘m’, ‘Y’]
})

export default {
name: ‘app’,
components: {
SmartCleave
},
data () {
return {
date: ‘’
}
},
methods: {
logIt (val) {
console.log(‘cahnged’, val)
this.date = val
}
}
}
</script>

<style>

#app {
font-family: ‘Avenir’, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* text-align: center; */
color: #2c3e50;
margin-top: 60px;
}
</style>

[Vue.js] Best Practice for Reacting to Params Changes with Vue Router

When using vue.js Router with routes like /foo/:val you have to add a watcher to react for parameter changes. That results in somewhat annoying duplicate code in all views that have parameters in the URL.

This could look like the following example:

export default {
// […]
created() {
doSomething.call(this);
},
watch: {
‘$route’ () {
doSomething.call(this);
}
},
}

function doSomething() {
// e.g. request API, assign view properties, …
}

Is there any other way to overcome that? Can the handlers for created and $route changes be combined? Can the reuse of the component be disabled so that the watcher would not be necessary at all? when using vue.js 2, but this might be interesting for vue.js 1, too.

Solution :

One possible answer that I just found thanks to a GitHub issue is the following.

It is possible to use the key attribute that is also used for v-for to let vue.js track changes in the view. For that to work, you have to add the attribute to the router-view element:

<router-view :key=”$route.fullPath”></router-view>

After you add this to the view, you do not need to watch the $route anymore. Instead, Vue.js will create a completely new instance of the component and also call the created callback.

However, this is an all-or-nothing solution. It seems to work well on the small application that when currently developing. But it might have effects on performance in another application. If you really want to disable the reuse of the view for some routes only, you can have a look at setting the key’s value based on the route. But I don’t really like that approach.

[Vue.js] Search Box and Checkbox filter with Vue

when trying to build filter system with Vue.

Updated

Filters working, but all the functions computed are separeted functions. So How can I make those in one function and use it.

export default {

data() {
return {
estates: [],
search: ‘’,
regions:[‘’,’’,’’],
checkedRegions:[]
}
},
created(){
axios.get(‘/ajax’).then((response) => {
this.estates = response.data;
});
},
computed: {
one: function() {
var result = this.estates.filter((estate) =>
estate.building_name.match(this.search)
);
if(this.checkedRegions.length && this.checkedRooms.length) {
return result.filter(estate => this.checkedRegions.includes(estate.region) && this.checkedRooms.includes(estate.rooms))
}
return result;
}
}
}
<div class=”container-fluid”>
<div class=”row”>
<div class=”col-md-9”>
<input type=”text” v-model=”search” name=”” placeholder=”search estate” value=””>
<div v-for=”estate in filteredestate” class=”card-body”>
<h2>{estate.building_name}</h2>
<p>{estate.address}</p>
</div>
</div>
</div>
</div>

filteredestate filteredRegions and filteredRooms make one function. for example how to return those function with && ? And use it in this div.

<div v-for=”estate in oneFunction” class=”card-body”>

Solution :

Set the filter search result first as variable and you can check filter by or(||) expression !

I modified this inside arrow function by setting to that variable and on the last line return result as default

one: function() {
var that = this;
var result = this.estates.filter((estate) =>
estate.building_name == that.search;
);
if(this.checkedRegions.length || this.checkedRooms.length) {
return result.filter(estate => that.checkedRegions.includes(estate.region) || that.checkedRooms.includes(estate.rooms))
}
// when region and room length is 0
return result;
}
}

Solution 2:

rooms and regions are arrays. So you need to iterate through these arrays in order to render the checkboxes.

instead of this:

<input type=”checkbox” v-model=”checkedLocations” v-bind:value=”regions”> <input/>
<input type=”checkbox” v-model=”checkedLocations” v-bind:value=”regions”> <input/>
<input type=”checkbox” v-model=”checkedLocations” v-bind:value=”regions”><input/>

should be like this:

<template v-for=”region in regions”>
<input type=”checkbox” v-model=”checkedLocations” v-bind:value=”region.id”>region.region<input/>
</template>

similar should be done with rooms.

Also, in js part, you have checkedRegions while in template you have checkedLocations. I guess this should be too checkedRegions.

[Vue.js] Passing event and argument to v-on in Vue.js

I pass a parameter in v-on:input directives. If I don’t pass it, I can access the event in the method. Is there any way I can still access the event when passing the parameter to the function. Not that when using vue-router:

This is without passing the parameter. I can access the event object

HTML

<input type=”number” v-on:input=”addToCart” min=”0” placeholder=”0”>

Javascript

methods: {
addToCart: function (event) {

// I need to access the element by using event.target
console.log(‘In addToCart’)
console.log(event.target)
}
}

This is when passing the parameter. I can’t access the event object

HTML

<input type=”number” v-on:input=”addToCart(ticket.id)” min=”0” placeholder=”0”>

Javascript

methods: {
addToCart: function (id) {

// How can I access the element by using event
console.log(‘In addToCart’)
console.log(id)
}
}

Here is some snippet of the code, should be good enough to replicate the problem that when having

https://jsfiddle.net/lookman/vdhwkrmq/

Solution :

If you want to access event object as well as data passed, you have to pass event and ticket.id both as parameters, like following:

HTML

<input type=”number” v-on:input=”addToCart($event, ticket.id)” min=”0” placeholder=”0”>

Javascript

methods: {
addToCart: function (event, id) {
// use event here as well as id
console.log(‘In addToCart’)
console.log(id)
}
}

See working fiddle: https://jsfiddle.net/nee5nszL/

Edited: case with vue-router

In case you are using vue-router, you may have to use $event in the v-on:input method like following:

<input type=”number” v-on:input=”addToCart($event, num)” min=”0” placeholder=”0”>

Here is working fiddle.

Solution 2:

You can also do something like this…

<input @input=”myHandler(‘foo’, ‘bar’, …arguments)”>

Evan You himself recommended this technique in one post on vue.js forum. In general some events may emit more than one argument. Also as documentation states internal variable $event is meant for passing original DOM event.

[Vue.js] Accessing Vuex state when defining Vue-Router routes

there is the following Vuex store (main.js):

import vue.js from ‘vue’
import Vuex from ‘vuex’

Vue.use(Vuex)

//init store
const store = new Vuex.Store({
state: {
globalError: ‘’,
user: {
authenticated: false
}
},
mutations: {
setGlobalError (state, error) {
state.globalError = error
}
}
})

//init app
const app = new Vue({
router: Router,
store,
template: ‘<app></app>’,
components: { App }
}).$mount(‘#app’)

I also have the following routes defined for Vue-Router (routes.js):

import vue.js from ‘vue’
import VueRouter from ‘vue-router’

Vue.use(VueRouter)

//define routes
const routes = [
{ path: ‘/home’, name: ‘Home’, component: Home },
{ path: ‘/login’, name: ‘Login’, component: Login },
{ path: ‘/secret’, name: ‘Secret’, component: SecretPage, meta: { requiresLogin: true }
]

I’m trying to make it so that if the Vuex store’s user object has authenticated property false, have the router redirect the user to the Login page.

there is this:

Router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresLogin) && ???) {
// set Vuex state’s globalError, then redirect
next(“/Login”)
} else {
next()
}
})

The problem is I don’t know how to access the Vuex store’s user object from inside the beforeEach function.

I know that I can have the router guard logic inside components using BeforeRouteEnter, but that would clutter up each component. to define it centrally at the router level instead.

Solution :

As suggested here, what you can do is to export the store from the file it is in and import it in the routes.js. It will be something like following:

You have one store.js:

import Vuex from ‘vuex’

//init store
const store = new Vuex.Store({
state: {
globalError: ‘’,
user: {
authenticated: false
}
},
mutations: {
setGlobalError (state, error) {
state.globalError = error
}
}
})

export default store

Now in routes.js, you can have:

import vue.js from ‘vue’
import VueRouter from ‘vue-router’
import store from ./store.js

Vue.use(VueRouter)

//define routes
const routes = [
{ path: ‘/home’, name: ‘Home’, component: Home },
{ path: ‘/login’, name: ‘Login’, component: Login },
{ path: ‘/secret’, name: ‘Secret’, component: SecretPage, meta: { requiresLogin: true }
]

Router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresLogin) && ???) {
// You can use store variable here to access globalError or commit mutation
next(“/Login”)
} else {
next()
}
})

In main.js also you can import store:

import vue.js from ‘vue’
import Vuex from ‘vuex’

Vue.use(Vuex)

import store from ‘./store.js’

//init app
const app = new Vue({
router: Router,
store,
template: ‘<app></app>’,
components: { App }
}).$mount(‘#app’)

Solution 2:

I ended up moving the store out of main.js and into store/index.js, and importing it into the router.js file:

import store from ‘./store’

//routes

const routes = [
{ path: ‘/home’, name: ‘Home’, component: Home },
{ path: ‘/login’, name: ‘Login’, component: Login },
{ path: ‘/secret’, name: ‘Secret’, component: SecretPage, meta: { requiresLogin: true }
]

//guard clause
Router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresLogin) && store.state.user.authenticated == false) {
store.commit(“setGlobalError”, “You need to log in before you can perform this action.”)
next(“/Login”)
} else {
next()
}
})

Solution 3:

Managing the location state separate from the rest of the application state can make things like this harder than they maybe need to be. After dealing with similar problems in both Redux and Vuex, I started managing my location state inside my Vuex store, using a router module. You might want to think about using that approach.

In the specific case, you could watch for when the location changes within the Vuex store itself, and dispatch the appropriate “redirect” action, like this:

dispatch(“router/push”, {path: “/login”})

It’s easier than you might think to manage the location state as a Vuex module. You can use mine as a starting point if you want to try it out:

https://github.com/geekytime/vuex-router

Solution 4:

This is how i would to it.

In App.vue, I will keep a watcher on cookie that stores authentication details. ( Obviously I would store a token containing authentication details as cookie after authentication )

Now whenever this cookie becomes empty, I will route the user to /login page. Logging out deletes the cookie. Now if user hit back after logging out, now since the cookie doesnot exist, ( which requires user to be logged in ), user will be routed to login page.

[Vue.js] How can I display modal in modal on vue component?

My view blade like this :

<a href=”javascript:” class=”btn btn-block btn-success” @click=”modalShow(‘modal-data’)”>
Click here
</a>

<data-modal id=”modal-data”></data-modal>

If the button clicked, it will call dataModal component (In the form of modal)

dataModal component like this :

<template>
<div class=”modal” tabindex=”-1” role=”dialog”>
<div class=”modal-dialog” role=”document”>
<!– modal content data –>
<div class=”modal-content modal-content-data”>
<form id=”form”>
<div class=”modal-body”>

</div>

<button type=”submit” class=”btn btn-success” @click=”add”>
Save
</button>

</form>
</div>
<!– modal content success –>
<div class=”modal-content modal-content-success” style=”display: none”>
<div class=”modal-body”>

</div>
</div>
<!– modal content failed –>
<div class=”modal-content modal-content-failed” style=”display: none”>
<div class=”modal-body”>

</div>
</div>

</div>
</div>
</template>
<script>
export default{

methods:{
add(event){
const data = {

}
this.$store.dispatch(‘add’, data)
.then((response) => {
if(response == true)
this.$parent.$options.methods.modalContent(‘#modal-data’, ‘.modal-content-success’)
else
this.$parent.$options.methods.modalContent(‘#modal-data’, ‘.modal-content-failed’)
})
.catch(error => {
console.log(‘error’)
});
}
}
}
</script>

If response = true then modal with class = modal-content-success will appear

If response = false then modal with class = modal-content-failed will appear

if response = false, modal with class = modal-content-data still showing. So modal with class = modal-content-failed appears in modal with class class = modal-content-data

How can I do that?

How to order that when response = false, modal with class = modal-content-data still appear?

Please help me

Solution :

As i can see you are using bootstrap, this worked for me:

<template>
<div>
<div id=”modal-example” class=”modal” tabindex=”-1” role=”dialog”>
…insert rest of code here as is in the example
</div>
</div>
</template>

And then in the href link tag:

<a href=”javascript:void(0)” class=”btn btn-block btn-success” data-target=”#modal-example” data-toggle=”modal”>
Show Modal
</a>

[Vue.js] Vue.js - how to properly conditionally set click handler code

Currently, there is a modal that pops up with a button on it. Depending on some data coming down, when changing the text and functionality of the button on the modal. when using a computed to change the button text and another computed to change the button @click code. If the condition is true, it sets the button’s @click code to another javascript method.

I’m finding that as soon the modal gets opened, that function that is supposed to be getting attached to the @click of the button is actually getting called and run. Obviously, this is not what I want.

vue.js component HTML code:

<button
variant=”primary”
outline
type=”button”
@click=”continueButtonClick”
\>
{ continueButtonText }
</button>

vue.js component JS code:

computed: {
continueButtonClick() {
let vm = this;
let click = vm.close;
console.log(“itemMapText: “, vm.item.itemMapText);
if(vm.item.itemMapText === “map_displayText_viewPriceInCart”) {
click = vm.updateCartVue(vm.item.itemId);
}
return click;
},
continueButtonText() {
let vm = this;
let buttonText = “Continue Shopping”;
if(vm.item.itemMapText === “map_displayText_viewPriceInCart”) {
buttonText = “Remove From Cart”;
}
return buttonText;
},

Also, the vm.close does seem to be getting properly attached as that only runs when the button is clicked.

Solution :

Please don’t do that ! vue.js wants you to separate state from code from markup. If you do this, you’ve got a little bit of state living in the markup. @click should just point to a method, and all the conditional logic should be in the method. Just use if() inside the handler in the methods block to differentiate the two cases. It will be much easier to follow.

The thing about computed is that you don’t know/shouldn’t care when it runs. I suppose you could get into returning a function from a computed, using bind() to link the arguments, but I recoil in horror. I can’t see why it has to be so complex.