link2603 link2604 link2605 link2606 link2607 link2608 link2609 link2610 link2611 link2612 link2613 link2614 link2615 link2616 link2617 link2618 link2619 link2620 link2621 link2622 link2623 link2624 link2625 link2626 link2627 link2628 link2629 link2630 link2631 link2632 link2633 link2634 link2635 link2636 link2637 link2638 link2639 link2640 link2641 link2642 link2643 link2644 link2645 link2646 link2647 link2648 link2649 link2650 link2651 link2652 link2653 link2654 link2655 link2656 link2657 link2658 link2659 link2660 link2661 link2662 link2663 link2664 link2665 link2666 link2667 link2668 link2669 link2670 link2671 link2672 link2673 link2674 link2675 link2676 link2677 link2678 link2679 link2680 link2681 link2682 link2683 link2684 link2685 link2686 link2687 link2688 link2689 link2690 link2691 link2692 link2693 link2694 link2695 link2696 link2697 link2698 link2699 link2700 link2701 link2702 link2703 link2704 link2705 link2706 link2707 link2708 link2709 link2710 link2711 link2712 link2713 link2714 link2715 link2716 link2717 link2718 link2719 link2720 link2721 link2722 link2723 link2724 link2725 link2726 link2727 link2728 link2729 link2730 link2731 link2732 link2733 link2734 link2735 link2736 link2737 link2738 link2739

[Vue.js] How to calculate SVG viewBox via vue.js?

how to automatically evaluate the viewbox of SVG via vue.js?

My code:

Vue.component(‘icon’, {
props: {
width: {
type: Number,
default: 24
},
height: {
type: Number,
default: 24
},
viewBox: {
default: 0 0 + width + height
}
},
template: ‘<svg xmlns=”http://www.w3.org/2000/svg" :viewBox=”viewBox” :width=”width” :height=”height”></svg>’,
})

0 0 + width + height doesn’t work, how to fix it? Im new in Vue.js.

Thanks!

Solution :

In addition to the fact that you should define viewBox as a computed value like @ittus pointed out, 0 0 + width + height does not evaluate to a string because:

a) 0 0 is not valid javascript (Uncaught SyntaxError: Unexpected number)

b) width and height are both numbers. 0 + width + height would evaluate to a number, 48 by default.

Use one of the following to create a string:

Concatenation (Read more here):

viewBox: {
default: ‘0 0 ‘ + this.width + ‘ ‘ + this.height
}

or a template literal (Read more here):

viewBox: {
default: `0 0 ${this.width} ${this.height}`
}

Solution 2:

You should use computed instead

Vue.component(‘icon’, {
props: {
width: {
type: Number,
default: 24
},
height: {
type: Number,
default: 24
}
},
computed: {
viewBox() {
return ‘0 0 ‘ + this.width + ‘ ‘ + this.height
}
}
template: ‘<svg xmlns=”http://www.w3.org/2000/svg" :viewBox=”viewBox” :width=”width” :height=”height”></svg>’,
})

[Vue.js] Creating project in vue taking time

I typed vue.js create “project name” and it is installing packages for some long time.

there is no error messages it just keeps on installing packages

Solution :

there is encountered significant speed issues with vue-cli it definitely slows down the computer. Try closing everything except the terminal and see if that helps. The next step would be to free up memory by killing unneeded processes.

[Vue.js] MathJax not always rendering with Vue filtered list

I’m trying to build a filtered list in vue.js with equations rendered with MathJax, and it seems to be having some problems, since the equations renders on the first load, but when I search for terms, some equations render and some don’t, I can’t understand why.
Basically on the first load, if I type a character in my search bar, everything renders correctly, but when I search more, or erase it and do it again, it doesn’t, as you can see in these images:

my vue.js code is as follows:

var analisiMatematica = new Vue({

el: ‘#searcher’,
data: {
searchQuery: ‘’,
isResult: false,
results: [],
//json: ‘json/analisimatematica.json’,
error: ‘’
},

mounted: function() {
axios.get(‘./json/analisimatematica.json’)
.then(function(response) {
this.results = response.data.Domande;
console.log(this.results);
}.bind(this))
.catch(function(error) {
this.error = error.data;
console.log(error.data);
}.bind(this));
},

methods: {
removeSearchQuery: function() {
this.searchQuery = ‘’;
this.isResult = false;
},
submitSearch: function() {
this.isResult = true;

}
},
computed: {
filteredObj: function() {
var list = [];
this.results.forEach(function(el) {
if(el.domanda.toLowerCase().indexOf(this.searchQuery.toLowerCase()) > -1) {
list.push(el);
}
}.bind(this))
return list;
}
}

});

MathJax is loaded in my html file’s <head> like this:

<script type=”text/x-mathjax-config”>
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ [‘$’,’$’], [“\\(“,”\\)”] ],

}
});
</script>
<script type=”text/javascript” async
src=”https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM\_CHTML">
</script>

While the vue.js app section is like this:

<div id=”searcher”>
<p v-show=”error” v-html=”error”></p>
<form class=”searchForm” v-on:submit.prevent=”submitSearch”>
<input type=”text” name=”queryInput” v-model=”searchQuery” placeholder=”Che domanda cerchi?” @keyup=”submitSearch”>
<span v-show=”searchQuery” class=”removeInput” @click=”removeSearchQuery”>+</span>
</form>
<div class=”results” v-show=”isResult”>
<ul>
<li v-for=”result in filteredObj”>
<p id=”domanda”>{ result.domanda }</p>
<p id=”risposta”>{ result.risposta }</p>
</li>
</ul>

</div>
</div>

Solution :

All you need is to trigger MathJax to render again when filteredObj is changed. Watch filteredObj:

watch: {
filteredObj: function () {
if (‘MathJax’ in window) {
this.$nextTick(function() {
MathJax.Hub.Queue([“Typeset”,MathJax.Hub, document.body])
});
}
}
}

var analisiMatematica = new Vue({
el: ‘#searcher’,
data: {
searchQuery: ‘’,
isResult: false,
results: [],
//json: ‘json/analisimatematica.json’,
error: ‘’
},

mounted: function() {
this.results = [{domanda: ‘$a+b=c$’, risposta: ‘$a+b=c$’}]
},

methods: {
removeSearchQuery: function() {
this.searchQuery = ‘’;
this.isResult = false;
},
submitSearch: function() {
this.isResult = true;

}
},
computed: {
filteredObj: function() {
var list = [];
this.results.forEach(function(el) {
if(el.domanda.toLowerCase().indexOf(this.searchQuery.toLowerCase()) > -1) {
list.push(el);
}
}.bind(this))
return list;
}
},
watch: {
filteredObj: function () {
if (‘MathJax’ in window) {
this.$nextTick(function() {
MathJax.Hub.Queue([“Typeset”,MathJax.Hub, document.body])
});
}
}
}

});
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script type=”text/x-mathjax-config”>
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ [‘$’,’$’], [“\\(“,”\\)”] ],

}
});
</script>
<script type=”text/javascript” async
src=”https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM\_CHTML">
</script>

<div id=”searcher”>
<p v-show=”error” v-html=”error”></p>
<form class=”searchForm” v-on:submit.prevent=”submitSearch”>
<input type=”text” name=”queryInput” v-model=”searchQuery” placeholder=”Che domanda cerchi?” @keyup=”submitSearch”>
<span v-show=”searchQuery” class=”removeInput” @click=”removeSearchQuery”>+</span>
</form>
<div class=”results” v-show=”isResult”>
<ul>
<li v-for=”result in filteredObj”>
<p id=”domanda”>{ result.domanda }</p>
<p id=”risposta”>{ result.risposta }</p>
</li>
</ul>

</div>
</div>

[Vue.js] VueRouter this.$route.query always empty

I’m trying to get the query param code, but $route.query is always empty. I’ve used function mode per the docs. What is missing?

Router:

// use vue-router
import Router from ‘vue-router’
Vue.use(Router)

// create router
const router = new Router({
routes: [
{
path: ‘/‘,
component: Home,
props: (route) => ({ code: route.query.code })
}
]
})

Home.vue

<template>
<div>
<Navbar />
<FlatHeader />
<v-content>
<ComingSoon />
<Changes />
<EmailSubscribe />
</v-content>
<AuthorizationModal />
</div>
</template>

<script>
import AuthorizationModal from ‘./components/AuthorizationModal’;
import FlatHeader from ‘./components/FlatHeader’;
import ComingSoon from ‘./components/ComingSoon’;
import Changes from ‘./components/Changes’;
import EmailSubscribe from ‘./components/EmailSubscribe’;

export default {
name: ‘Home’,
components: {
FlatHeader,
ComingSoon,
Changes,
EmailSubscribe,
AuthorizationModal
},
props: {
code: {
type: String,
default: null
}
},
methods: {
},
mounted() {
console.log(this.$route)
}
}

</script>

$route console output:

Solution :

I resolved this by setting the mode on Router to ‘history’.

Router:

// create router
const router = new Router({
mode: ‘history’, // add ‘history’ mode
routes: [
{
path: ‘/‘,
component: Home,
props: (route) => ({ code: route.query.code })
}
]
})

[Vue.js] Laravel Vue SPA login

I just created vue.js + Laravel SPA login but I’m not sure if it’s safe enough. I’m new in vue.js :)

I’m using JWT Auth. When user enter credentials and submit form, Auth on Laravel side returns user model with token. This user is stored in local storage. In my vue.js router I created middleware which run beforeEach view change. This is working good but there is not actual token in database related to this user. When I manually change token in storage I’m still passing middleware because token is not checked anymore. It just check if exists in local storage… Should I store token in DB and check it on every view change? Or…??

Solution :

It doesn’t sound like its safe, no :)

I’ve never used Laravel, so I can’t talk about it specifically, but I can explain how the process is suppose to work.

In the server, you should have a middlewere or somekind of logic that reads the token and verifies it integrity. The token itself is just a Base64 string with three components

Header
Payload (the actual data)
Signature

If you have the token, its easy to read the payload, because its just Base64 string. So its not enough just to read that, you need to make sure that the signature is correct.

When you create a JWT token you do so with a secret, when there’s a request to the server. The server should verify the signature to make sure that this is a valid token. If you don’t have the secret you can’t verify the signature. Only you should have the secret.

This stops “me as an attacker” to send a token with some fake payload. By verifying the signature you are making sure that this is the token you created, not some fake token I’m sending to the website.

You should also not store that token in a local storage. Local storage should never contain information like token or password, because is just a dictionary/map that’s accessable for everybody. So I can make a website that reads the local storage, get the token you created, and since this is the token with a correect signature I can now make requests to the website.

I would reccomend storing a JWT token in a httpOnly cookie on https (safe: true option in most environments). The browser can’t read httpOnly cookies, only the server.

When making requests from the VueJS app to the server, like saving a blog post the server should

Never trust the payload in the JWT blindly.
Never trust user information from the VueJS app.
Always verify the user on the server side (by verifying the signature of the token in the example)

For example

methods: {
saveBlogPost() {
axios.post(‘/api/save’, {
title: ‘My blog title’
userId: ‘bergur’
})
}
}

the server should never, never read that userId sent from the VueJS app. The JWT middlewere should check the JWT, verify its integrity and then use the information from the payload.

Edit: I answered a similar post about securing VueJS apps. You can find it here: VueJS Secure with Auth0 - How is it secure?

Basically: Its fine to store information in the client that help to make the user interface make sense, but when doing the actual work like saving into the database or fetching some private data the server should always verify the user.

[Vue.js] What is <router-view key=$route.fullPath> ?

I’m completely new to Vue.js and I think there is a bit of understanding of how a router works with things like:

<router-link to=”/“>

But when not really understanding what the following line does:

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

I believe router-view by itself makes sure the content is displayed but what does the key part mean?

Solution :

See Special Attributes - key

It can also be used to force replacement of an element/component instead of reusing it. This can be useful when you want to:

Properly trigger lifecycle hooks of a component
Trigger transitions

$route.fullPath is defined as

The full resolved URL including query and hash.

If you bind key to $route.fullPath, it will always “force a replacement” of the <router-view> element / component every time a navigation event occurs.

As mentioned above, this is most probably done in order to trigger a transition / animation.

[Vue.js] Unable to access data in props

I need to access the data passed through props to built a heatmap. The data is there but I can’t use it.

to use my getData() function to iterate over my data.

If I call the “gamedata.teamA.players[0].pos[0].posY” in the template it prints the position, but I can’t use it on functions.

export default {
name: “HeatMap”,
props: [“gamedata”],
data: function() {
return {
teamdata: [[0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0]],
chartOptions: {

},
methods: {
getData: function() {
for(var i = 0; i < this.gamedata.teamA.players.length;i++ ){
for(var j = 0; j < this.gamedata.teamA.players[i].pos.length;j++){
this.teamdata[this.getPos(this.gamedata.teamA.players[i].pos[j].posY)][this.getPos(this.gamedata.teamA.players[i].pos[j].posX)]++;
}
}
},
…,
mounted() {
this.getData();
this.series = this.populate();
}

};

I get the following error on the console:

“[vue.js warn]: Error in mounted hook: “TypeError: this.gamedata.teamA is undefined””

Solution :

It seems that the data wasn’t loaded when I try to mounted(). Using a watcher before the mounted made it work.

watch: { gamedata(){ this.getData()} },
mounted() {
this.series = this.populate();
}

[Vue.js] vue.js - issues with the background image covering on viewport size on Desktop

there is a component game that interact with a data.json file where all my data is (including different background images). And in the page game different backgrounds so i did this:

v-bind:style=”{ ‘background’: ‘url(‘+ step.img +’)’ + ‘no-repeat center fixed’}”

But when i add “cover” to the list the image disappear from the viewport.

The path is /game/:id, so this is how you go to one page to another within the same component.

PS: it’s a game where there’s a question with multiple solutions and you have to choose one to pass the step and go to the one following…

v-bind:style=”{ ‘background’: ‘url(‘+ step.img +’)’ + ‘no-repeat center fixed cover’}”

doesn’t work

this is in my data.json file:

“img”: “../assets/images/bg1.png”

@DrCord this is what i wrote

<template>
<div rel=”preload” v-bind:style=”{ ‘background’: ‘url(‘+ step.img +’)’ + ‘no-repeat center fixed’ }”>
<section>
<h1>{ step.title }</h1>
</section>

<ul>
<li v-on:click=”doActions(action)”
v-for=”action in step.actions”
:key=”action.step”
v-show=”canDoAction(action)”
\>

</li>

</ul>
</div>
</template>

@Daniel Do you mean just an img tag ( Sorry i’m a beginner )

Solution :

According to W3C documentation cover in the compact background attributes mode should be used with / before it, like so: ‘url(‘+ step.img +’)’ + ‘no-repeat center / cover’, check my working snippet answer below.

<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id=”el”>
<div rel=”preload” :style=”{ ‘background’: ‘url(‘+ step.img +’)’ + ‘no-repeat center / cover’ }”>
<section>
<h1>{ step.title }</h1>
</section>

<ul>
<li @click=”doActions(action)”
v-for=”action in step.actions”
:key=”action.step”
v-show=”canDoAction(action)”
\>

</li>

</ul>
</div>
</div>

<script>
new Vue({
el: ‘#el’,
data: {
step: {
title: ‘This is title’,
img: ‘https://via.placeholder.com/1000'
}
}
})
</script>

[Vue.js] Laravel and Vue authentication form reload on failed login

I’m new on laravel 5.8 and vue.js and I’m using veeValidate and a basic FORM to login having:

method=”POST” action=”/login” and values: email, password and _token for csrf_token

and a button for submission like that:

<v-btn>@click=”validate”>Login</v-btn>

When user click on button the vue.js method validate is invoked:

methods: {
validate() {
this.$validator.validateAll().then((result) => {
if (result) {
//Manually submit form if not errors
document.getElementById(“login_form”).submit();
}
})
},
}

This method run the veeValidate validator and if true then the form is submitted (POST to the action path). On error it update the frontend errors alert (ie. missing data or password too short).

The route redirect the POST request to the Laravel’s Controller Auth/LoginController@login which has the protected $redirectTo = ‘/welcome’;

$redirectTo is the landing page in case of no errors (Login). But if validator fail it redirect to the form page which is reloaded with no alerts.

I like the simple flow but I would like to show the failed backend reasons (IE: any feedback or login attempts);

How can I get the LoginController@login bad response to show a message into the vue.js component?

Solution :

If you want a more custom login form submition behavior you will need to do the Http request manually.

To do that hook into the form submit event

<form v-on:submit.prevent=”onFormSubmit”>

Note the lack of an action or method attribute! You do not need this when using this approach.

When handling the submit you simply do the Http request manually.

methods: {
onFormSubmit() {
const csrfToken = document.querySelector(“meta[name=”_token”]“).getAttribute(“content”);

fetch(“/login”, {
method: “POST”,
headers: new Headers({
“Content-Type”: “x-www-form-urlencoded”,
“X-XSRF-TOKEN”: csrfToken
}),
body: JSON.stringify(<required parameters>)
})
.then(res => res.json())
.then(res => {
if(res.ok) {
// Do login
} else {
// Show errors
}
});
}
}

On the backend make sure to only return a 200 status code when the operation succeeds and return an error code together with something like an errors property to be able to read the errors on the Frontend.

You can easily implement this in laravel by using the build in laravel validator

[Vue.js] VueJs How to reuse bootstrap modal dialog

I’ve created three simple buttons that will trigger three different bootstrap modal dialog. The modal dialogs are “Add Product”, “Edit Product” and “Delete Product”. Both the Add and Edit modal dialogs contain a form with two input elements, whereas the Delete modal dialog contains a simple text. I realise that my code becomes very messy and hard to maintain. Hence, there is the following question:

1) How do I reuse the modal dialog, instead of creating 3 separate dialogs?

2) How do I know which modal dialog has been triggered?

Update: I’ve developed a soultion where I will include conditional statements such as v-if, v-else-if and v-else to keep track of which button the user click. However, I still feel that there is a better solution to this. Can anyone help/advice me?

Below is my current code:

<template>
<div>
<b-button v-b-modal.product class=”px-4” variant=”primary” @click=”addCalled()”>Add</b-button>
<b-button v-b-modal.product class=”px-4” variant=”primary” @click=”editCalled()”>Edit</b-button>
<b-button v-b-modal.product class=”px-4” variant=”primary” @click=”deleteCalled()”>Delete</b-button>

<!– Modal Dialog for Add Product –>
<b-modal id=”product” title=”Add Product”>
<div v-if=”addDialog”>
<form @submit.stop.prevent=”submitAdd”>
<b-form-group id=”nameValue” label-cols-sm=”3” label=”Name” label-for=”input-horizontal”>
<b-form-input id=”nameValue”></b-form-input>
</b-form-group>
</form>

<b-form-group id=”quantity” label-cols-sm=”3” label=”Quantity” label-for=”input-horizontal”>
<b-form-input id=”quantity”></b-form-input>
</b-form-group>
</div>

<div v-else-if=”editDialog”>
<form @submit.stop.prevent=”submitEdit”>
<b-form-group id=”nameValue” label-cols-sm=”3” label=”Name” label-for=”input-horizontal”>
<b-form-input id=”nameValue” :value=”productName”></b-form-input>
</b-form-group>
</form>

<b-form-group id=”quantity” label-cols-sm=”3” label=”Quantity” label-for=”input-horizontal”>
<b-form-input id=”quantity” :value=”productQuantity”>5</b-form-input>
</b-form-group>
</div>

<div v-else>
<p class=”my-4”>Are You Sure you want to delete product?</p>
</div>
</b-modal>
</div>
</template>

<script>
export default {
data() {
return {
productName: “T-Shirt”,
productQuantity: 10,
addDialog: false,
editDialog: false,
deleteDialog: false
};
},
methods: {
addCalled() {
this.addDialog = true;
},
editCalled() {
this.editDialog = true;
this.addDialog = false;
this.deleteDialog = false;
},
deleteCalled() {
this.deleteDialog = true;
this.addDialog = false;
this.editDialog = false;
}
}
};
</script>

<style>
</style>

Solution :

Update

Now, You might think how will you close the modal and let the parent component know about it.
On click of button trigger closeModal for that

Create a method - closeModal and inside commonModal component and emit an event.

closeModal() {
this.$emit(‘close-modal’)
}

Now this will emit a custom event which can be listen by the consuming component.

So in you parent component just use this custom event like following and close the modal

<main class=”foo”>
<commonModal v-show=”isVisible” :data=”data” @close- modal=”isVisible = false”/>
<!– the further code –>
</main>

So as per the question

A - How do I reuse the modal dialog, instead of creating 3 separate dialogs

Make a separate modal component, let say - commonModal.vue.

Now in the commonModal.vue, accept single prop, let say data: {}.

Now in the html section of commonModal

<div class=”modal”>
<!– Use the received data here which get received from parent –>
<the modal code />
</div>

Now import the commonModal to the consuming/parent component. Create data property in the parent component, let say - isVisible: false and a computed property for the data you want to show in modal let say modalContent.

Now use it like this

<main class=”foo”>
<commonModal v-show=”isVisible” :data=”data” />
<!– the further code –>
</main>

The above will help you re-use modal and you just need to send the data from parent component.

Now second question will also get solved here How do I know which modal dialog has been triggered?

Just verify isVisible property to check if modal is open or not. If isVisible = false then the modal is not visible and vice-versa

Solution 2:

As already mentionned, I would have use slots and dynamic component rendering to accomplish what you’re trying to do in a cleaner way.

See snippet below (I didn’t make them modals as such but the idea is the same).

This way, you can have a generic modal component that deals with the shared logic or styles and as many modalContentsub-components as needed that are injected via the dedicated slot.

Vue.component(‘modal’, {
template: `
<div>
<h1>Shared elements between modals go here</h1>
<slot name=”content”/>
</div>
`
});

Vue.component(‘modalA’, {
template: `
<div>
<h1>when modal A</h1>
</div>
`
});

Vue.component(‘modalB’, {
template: `
<div>
<h1>when modal B</h1>
</div>
`
});

Vue.component(‘modalC’, {
template: `
<div>
<h1>when modal C</h1>
</div>
`
});

new Vue({
el: “#app”,
data: {
modals: [‘modalA’, ‘modalB’, ‘modalC’],
activeModal: null,
},
})
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id=”app”>
<button v-for=”modal in modals” @click=”activeModal = modal”> Open { modal } </button>
<modal>
<template slot=”content”>
<component :is=”activeModal”></component>
</template>
</modal>
</div>