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] Extending input focus to icon so will be clickable

there is a date picker component (v-date-picker) and when unable to get the icon, which is a Font Awesome Icon separate from the date-picker to open the calendar on focus (i.e. on click), I tried the solutions described here:
How to increase the clickable area of a <a> tag button?
With no luck, this should be straightforward but simply not working.

<template>
<div class=”v-date-picker”>
<v-date-picker
mode=”single”
:value=”date”
@input=”emit”
:placeholder=”placeholder”
popoverVisibility=”focus”
v-bind=”$attrs”
:max-date=”maxDate”
:min-date=”minDate”
\>
</v-date-picker>

<font-awesome-icon v-bind=”$attrs” :icon=”[‘far’,’calendar’]“ />
</div>
</template>
//skip all my code here….
<style lang=”scss”>
.v-date-picker {
position:relative;
input {
height: 36px;
display: block;
border: 1px solid #f3f3f3;
padding: 8px 12px;
font-size: 14px;
background: #f3f3f3;
box-shadow: 0 0 0 #EAEAEA;
width: 100%;
transition: all .3s ease-in-out;
border-radius: 4px;

&:hover {
border-color: #ddd;
box-shadow: none;
}

&:focus {
border-color: #ea7d1c;
box-shadow: none;
}
}
}

input::-webkit-input-placeholder { color: #ccc;}
input::-webkit-input-placeholder { color: #ccc;}
input::-moz-placeholder { color: #ccc;}
input:-ms-input-placeholder { color: #ccc;}

.fa-calendar {
position: absolute;
right: 10px;
top: 10px;
font-size: 16px;
color: #666;
}
.date-picker .vdp-datepicker__calendar .cell.selected,
.date-picker .vdp-datepicker__calendar .cell.selected.highlighted,
.date-picker .vdp-datepicker__calendar .cell.selected:hover {
background: #ea7d1c;
color: white;
}
.date-picker .vdp-datepicker__calendar .cell:not(.blank):not(.disabled).day:hover,
.date-picker .vdp-datepicker__calendar .cell:not(.blank):not(.disabled).month:hover,
.date-picker .vdp-datepicker__calendar .cell:not(.blank):not(.disabled).year:hover {
border-color: #ea7d1c;
}
</style>

Solution :

Forward the click event to the datepicker (which my button here is standing in for):

new Vue({
el: ‘#app’,
methods: {
forward(event) {
const b = this.$refs.dp;

b.dispatchEvent(new MouseEvent(event.type, event));
},
action() {
alert(‘Date picker!’);
}
}
});
button {
margin-top: 4rem;
}
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js">
</script>
<div id=”app”>
<div @click=”forward”>Click me</div>
<button ref=”dp” @click=”action”>Not me</button>
</div>

[Vue.js] Vue Filepond Image Crop

I’m using filepond with VueJS for uploading images. I should crop images on upload if I want.

I registered filepond plugin globally.

import vue.js from ‘vue’;
import vueFilePond from ‘vue-filepond’;
import FilePondPluginFileValidateType from ‘filepond-plugin-file-validate-type’;
import FilePondPluginImagePreview from ‘filepond-plugin-image-preview’;
import FilePondPluginImageCrop from ‘filepond-plugin-image-crop’;

import ‘filepond/dist/filepond.min.css’;
import ‘filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css’;

const FilePond = vueFilePond(FilePondPluginFileValidateType, FilePondPluginImagePreview, FilePondPluginImageCrop);
Vue.component(‘filePond’, FilePond);

Then I’m using component

<file-pond
name=”image”
ref=”pond”
:label-idle=”$t(‘complaint_detail.label-idle’)”
:allow-multiple=”false”
accepted-file-types=”image/*“
:server=”{ process }”
:allowImagePreview=”true”
:allowImageCrop= “true”
:allow-revert = “false”
v-on:init=”handleFilePondInit”
v-on:addfile=”handleFilePondAddFile”
/>

And here is my process method

process(fieldName, file, metadata, load) {
load(file);
},
handleFilePondInit() {
this.$refs.pond.getFiles();
},

But with this codes image cropping doesn’t work. In documentation there is only allowImageCrop additionally but it doesn’t work for me. Here is the link for documentation:
https://pqina.nl/filepond/docs/patterns/plugins/image-crop/

Solution :

You need to define a crop ratio using the imageCropAspectRatio property.

For square crop:

<file-pond
image-crop-aspect-ratio=”1”
name=”image”
ref=”pond”
/>

[Vue.js] Vue.js saving data between redirects

I’m building a vue.js application with a redirect to an external credit card payment page which then redirects back to my app. How do I keep my app data between these redirects? (quite a large amount of data otherwise I might have passed it in the URL params). What is the best practice to do that in Vue.js?

Solution :

If you need to store something while the page is no longer loaded, you have to use the Web Storage api. You can use sessionStorage, localStorage or maybe something like IndexedDB. Simply restore the state from there whenever the application loads again.

[Vue.js] Vue Events - Can't listen to $emit event from child component

I’m having a simple issue, that I just can’t figure out why it isn’t working.
there is a child component “app-buttons”, where there is an input field, to listen to, so i can filter a list based on the input value.

If i put the input in the root component where there is the list, all works good. But to split it up, and $emit the search input value, to the parent en then use it.

// THIS IS THE COMPONENT WHERE I WAN’T TO LISTEN TO THE SEARCH INPUT

import Buttons from ‘./app-buttons.js’;
import Event from ‘./vue-event.js’;

export default Vue.component(‘post-item’, {

template: `
<section class=”posts flex” v-if=”posts”>
<app-buttons :posts=”posts”></app-buttons>

<transition-group name=”posts” tag=”section” class=”posts flex”>
<article class=”postitem” :class=”{ ‘danger’: !post.published }” v-for=”post in posts” :key=”post.id”>
<p v-if=”post.published”>Post is published</p>
<p v-else>Post is <em><strong>not</strong></em> published</p>
<h4>{ post.title }</h4>

<button type=”submit” @click=”post.published = !post.published”>Change status</button>
</article>
</transition-group>
</section>
`,

data() {
return {
};
},

components: {
Buttons,
},

props: {
posts: Array,
filterdList: [],
},

created() {
console.log(‘%c Post items’, ‘font-weight: bold;color:blue;’, ‘created’);
},

computed: {
//filteredList() {
//return this.posts.filter(post => {
//return post.title.toLowerCase().includes(this.search.toLowerCase());
//});
//},
},

methods: {
update() {
console.log(‘test’);
}
}
});

// THIS IS THE COMPONENT IM TRIGGERING THE $EVENT FROM

import Event from ‘./vue-event.js’;

export default Vue.component(‘app-buttons’, {
template: `
<div class=”postswrapper flex flex–center flex–column”>

<section :class=”className” class=”flex flex–center”>
<button type=”button” @click=”showUnpublished”>Unpublish</button>
<button type=”button” @click=”shufflePosts”>Shuffle</button>
</section>

<section :class=”className”>
<input type=”text” v-model=”search” v-on:input=”updateValue” placeholder=”Search…” />
</section>

</div>
`,

data() {
return {
className: ‘buttons’,
search: ‘’,
}
},

props: {
posts: Array,
},

created() {
//console.log(this);
console.log(‘%c Buttons’, ‘font-weight: bold;color:blue;’, ‘created’);
},

methods: {
updateValue() {
//console.log(this.search);
this.$emit(‘searchquery’, this.search);
},

showUnpublished() {
this.posts.forEach(item => {
item.published = true;
})
},

shufflePosts() {
this.$emit(‘postshuffled’, ‘Fisher-Yates to the rescue’);
for (var i = this.posts.length - 1; i >= 0; i–) {
let random = Math.floor(Math.random() * i);
let temp = this.posts[i];

Vue.set(this.posts, i, this.posts[random]);
Vue.set(this.posts, random, temp);
}
},
}
});
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8”>
<title>vue.js JS</title>

<script src=”https://cdn.jsdelivr.net/npm/vue@2.6.6/dist/vue.js"></script>
<link rel=”stylesheet” type=”text/css” href=”style.css”>
</head>
<body>

<div id=”app”>
<app-header :logo=”logo” :name=”name”></app-header>
<post-item :posts=”posts” v-on:searchquery=”update” v-on:sq=”update” v-on:postshuffled=”update”></post-item>
</div>

<script type=”module”>
import AppHeader from ‘./components/app-header.js’;
import PostItem from ‘./components/post-item.js’;

const app = new Vue({
el: ‘#app’,
data: {
name: ‘vue.js App’,
logo: {
class: ‘vue-logo’,
src: ‘https://vuejs.org/images/logo.png',
},
components: {
AppHeader,
PostItem,
},
posts: [
{id: 1, title: ‘Test’, published: true},
{id: 2, title: ‘New post’, published: true},
{id: 3, title: ‘Added’, published: true},
{id: 4, title: ‘Another post’, published: true},
{id: 5, title: ‘In the future’, published: false},
{id: 6, title: ‘Last post’, published: true},
],
},

created() {
console.log(‘Created’);
},

mounted() {
console.log(‘Mounted’);
},

methods: {
update() {
console.log(‘updated’);
}
},
});
</script>

</body>
</html>

Solution :

You say:

there is a child component “app-buttons”, where there is an input field, i
want to listen to, so i can filter a list based on the input value.

You have:

<div id=”app”>
<app-header :logo=”logo” :name=”name”></app-header>
<post-item :posts=”posts” v-on:searchquery=”update” v-on:sq=”update” v-on:postshuffled=”update”></post-item>
</div>

That says you expect post-item to emit a searchquery event. It does not.

Within post-item, you have:

<app-buttons :posts=”posts”></app-buttons>

So you expect app-buttons to emit an event and post-item to implicitly bubble it up, but vue.js events do not bubble. If you want that behavior, you will need to have post-item handle the event:

<app-buttons :posts=”posts” v-on:searchquery=”$emit(‘searchquery’, $event)”></app-buttons>

Solution 2:

Okay so I’ve changed the markup, and it works. But would this be the best way to do it? :)
And thanks to Roy J for helping out.

import Event from ‘./vue-event.js’;
import Buttons from ‘./app-buttons.js’;

export default Vue.component(‘post-item’, {

template: `
<section class=”posts flex” v-if=”posts”>
<app-buttons :posts=”posts” v-on:searchquery=”update($event)”></app-buttons>

<transition-group name=”posts” tag=”section” class=”posts flex”>
<article class=”postitem” :class=”{ ‘danger’: !post.published }” v-for=”post in filteredItems” :key=”post.id”>
<p v-if=”post.published”>Post is published</p>
<p v-else>Post is <em><strong>not</strong></em> published</p>
<h4>{ post.title }</h4>

<button type=”submit” @click=”post.published = !post.published”>Change status</button>
</article>
</transition-group>
</section>
`,

data() {
return {
search: ‘’,
};
},

components: {
Buttons,
},

props: {
posts: Array,
},

created() {
console.log(‘%c Post items’, ‘font-weight: bold;color:blue;’, ‘created’);
},

computed: {
filteredItems(search) {
return this.posts.filter(post => {
return post.title.toLowerCase().indexOf(this.search.toLowerCase()) > -1
});
}
},

methods: {
update(event) {
this.search = event;
}
}
});

// Child component
import Event from ‘./vue-event.js’;

export default Vue.component(‘app-buttons’, {
template: `
<div class=”postswrapper flex flex–center flex–column”>

<section :class=”className” class=”flex flex–center”>
<button type=”button” @click=”showUnpublished”>Unpublish</button>
<button type=”button” @click=”shufflePosts”>Shuffle</button>
</section>

<section :class=”className”>
<input type=”text” v-model=”search” v-on:input=”updateValue” placeholder=”Search…” />
</section>

</div>
`,

data() {
return {
className: ‘buttons’,
search: ‘’,
}
},

props: {
posts: Array,
},

created() {
console.log(‘%c Buttons’, ‘font-weight: bold;color:blue;’, ‘created’);
},

methods: {
updateValue() {
this.$emit(‘searchquery’, this.search);
},

showUnpublished() {
this.posts.forEach(item => {
item.published = true;
})
},

shufflePosts() {
for (var i = this.posts.length - 1; i >= 0; i–) {
let random = Math.floor(Math.random() * i);
let temp = this.posts[i];

Vue.set(this.posts, i, this.posts[random]);
Vue.set(this.posts, random, temp);
}
},
}
});
Index same as before, just without alle the events on the components.

[Vue.js] Merge two states in Vuex store

there is a Vuex store with two states.

notes (notes that have been synced with the server/DB)
localNotes (which has not been synced with the server/DB, when synced with the server/DB they will be moved to ‘notes’ state)

when using these states to show the notes in a list with a getter. This getter merges the two objects and return the merge objects

The problem there is now is that if I add a new note to one of the states it will not be shown in the note list because the getter doesn’t pick the ‘change’ up. I think this happens because I return a variable instead of a function.

This is my getter:

const getters = {
notesObject: (state, getters, rootState, rootGetters) => {
let result = {};
let mergedObject = {…state.notes, …state.localNotes};
Object.keys(mergedObject).forEach(key => {
const item = mergedObject[key];
if (rootGetters[‘tags/activeKey’] === null) {
result[key] = item
} else if (item.tag_id === rootGetters[‘tags/activeKey’]) {
result[key] = item
}
});
return result;
},
};

Example object:

example: {
5: {
title: ‘Testing title’,
text: ‘text’
},
6: {
title: ‘Testing title’,
text: ‘text’
}
}

I hope someone can help me out to find the best solution for this. I was thinking about using a watcher, but I know these need to be avoided.

A solution was to let the watcher merge the two states into a new state.
Then the getter doesn’t have to merge the two objects

Solution :

Vue’s reactivity system doesn’t detect adding new properties. Try using Vue.set(object, key, value) when adding new notes.

In the mutation function replace state.localObject[payload.id] = payload; with Vue.set(state.localObject, payload.id, payload); The getter should then work properly.

[Vue.js] How to inlcude bootstrap-vue in vue.js with npm?

when using vue.js, webpack, npm and jQuery. Now to inlcude the framework bootstrap-vue.js in my project. I followed the guide of https://bootstrap-vue.js.org/docs via npm and included bootstrap-vue. While starting the build-process of npm, when getting too many errors with babel-runtime like:

ERROR in ./node_modules/bootstrap-vue/es/utils/popover.class.js
Module not found: Error: Can’t resolve ‘@babel/runtime/helpers/typeof’ in
‘C:\Users\abdul\WebstormProjects\editor\node_modules\
bootstrap-vue\es\utils’
@ ./node_modules/bootstrap-vue/es/utils/popover.class.js 10:38-78
@ ./node_modules/bootstrap-vue/es/directives/popover/popover.js
@ ./node_modules/bootstrap-vue/es/directives/popover/index.js
@ ./node_modules/bootstrap-vue/es/directives/index.js
@ ./node_modules/bootstrap-vue/es/index.js
@ ./src/main.js

main.js:

import vue.js from ‘vue’
import App from ‘./App’
import router from ‘./router’
import ‘jquery’
import Bootstrapvue.js from ‘bootstrap-vue’
import ‘bootstrap/dist/css/bootstrap.css’
import ‘bootstrap-vue/dist/bootstrap-vue.css’

Vue.use(BootstrapVue)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
el: ‘#app’,
router,
template: ‘<App/>’,
components: { App }
})

there is similar errors like this for other javascript files. Popover.class.js is one of them.

I except a successful run build with bootstrap-vue. Optional: I could include bootstrap-vue.js on other ways.

Solution :

Install vue-cli 3 and add bootstrap-vue.js as a plugin

Run these commands:

npm install -g @vue/cli

vue.js create project-name

cd project-name

vue.js add bootstrap-vue

The plugin will be automatically added and configured.

[Vue.js] How to make component tags start with a prefix in Vue?

when working on a project that I inherited from someone else, and I see a lot of <p-xxxx> tags, such as <p-page :has-something=”val1” :has-another=”val2” />, etc.(e.g. CompName –>

I’m looking around the directories and found a component called Page.vue.js that has such props in it: has-something and has-another. And structurally speaking, I’m sure the <p-page> corresponds to this component.

So how did this work? I checked the component’s name field and it says Page.

EDIT:
I should also note that the component isn’t registered at all. It’s not imported either. I’m guessing it has something to do with

import ‘@/globals’;
import ‘@/plugins’;

in main.js, because I know we’re using our proprietary UI component library. Can anyone point to where I can go read more about how this works? I thought I was pretty good at Vue, but apparently not good enough.

Solution :

It depends on how the component is registered in the parent component, for instance, if the Page component is registered as:

components: {
PPage: Page
}

Then in the template, you’ll refer to this component as <p-page …

Solution 2:

I figured it out.

In our proprietary library we’re using, components were being exported out with p- as a prefix, and the library was injected into the whole app via vue.config.js, so there wasn’t any importing in individual components.

[Vue.js] Why v-if is not showing the heading when boolean value changes?

when very new to vue.js js. when just learning to use it from laracasts. What to do is communicate between root class and subclass. Here, user will put a coupon code and when he changes focus it will show a text.

My html code is like this

<body>
<div id=”root”>
<coupon @applied=”couponApplied”>
<h1 v-if=”isCouponApplied”>You have applied the coupon.</h1>
</div>

<script src=”https://unpkg.com/vue@2.5.21/dist/vue.js"></script>
<script src=”main.js”></script>
</body>

My main.js is like this,

Vue.component(‘coupon’, {
template: ‘<input @blur=”applied”>’,
methods: {
applied()
{
this.$emit(‘applied’);
}
}
});

new Vue({
el: ‘#root’,
data: {
isCouponApplied:false,
},
methods:{
couponApplied()
{
this.isCouponApplied = true;
}
}
});

when checking using vue.js devtools extension in chrome. There is no error. The blur event is triggered. isCouponApplied also changes to true. But the h1 is not showing. Can anyone show me where I made the mistake?

Solution :

The problem is that you are not closing the <coupon> tag

<div id=”root”>
<coupon @applied=”couponApplied”></coupon>
<h1 v-if=”isCouponApplied”>You have applied the coupon.</h1>
</div>

Should fix the issue. If you don’t close the tag, the parser will auto-close it, but it will do so at the close of its wrapping container (the root div), so the h1 content will be seen as inside the <coupon> element, and will be replaced by the component’s template.

[Vue.js] Vue router-view loading parents component instead of its own

there is a route configuration like this:

{
path: ‘/‘,
component: Dashboard,
meta: { requiresAuth: true },
children: [
{ path: ‘home’, components: { container: Home } },
{
path: ‘post’,
components: { container: Post },
children: [
{ path: ‘add’, components: { container: Add } }
]
},
]
},

there is two <router-view>s, one is named container and the other is not named. when expecting the Add component to be loaded into the container router-view when I visit /post/add . But it’s loading the Post component. What am I missing?

EDIT:

Post.vue:

<template>
<div>
<p>when <code>./views/post/Post.vue</code></p>
</div>
</template>

Solution :

Try this, remove the Post component from the parent and add a new child component with path: ‘’. It’ll look like this -

{
path: ‘post’,
component: // Include a component which only renders the router-view
children: [
{ path: ‘’, components: { container: Post } },
{ path: ‘add’, components: { container: Add } }
]
},

Created a repl for the reference

[Vue.js] Emit an event from child mount and access from parent mount

Let’s say there is a component called child. there is data there that to access in my parent component. to emit an event in the childs mount: this.$emit(‘get-data’, this.data) before finally retrieving it in the parent mount. Is this possible to do / practical? If it is how can one achieve it? If not, what are some better alternatives?

Cheers.

Solution :

when not aware if being able to listen for $emit’d data, from a child mount(), inside a parent mount(). You need to bind the listener to the child component within the parent template. Typical example using SFC

Child.vue:

export default{
name: ‘child’,
mount(){
this.$emit(‘get-data’, this.data);
}
}

Parent.vue:

<template>
<div>
<child v-on:get-data=”doSomething”></child>
</div>
</template>
<script>
import Child from ‘./Child’;
export default{
name: ‘parent’,
components: { Child },
methods(){
doSomething(data){
//Do something with data.
}
}
}
</script>

Solution 2:

An alternative way to pass data from a child to a parent is scoped slots. I think that is more appropriate than events in the case (only pass data without any relation to a real event). But I’m not sure that I fully understood you.

Solution 3:

I would use the created hook not mounted because you only need access to reactive data and events. You could emit the whole child component and then drill into its data as needed.

template

<child-component @emit-event=”handleEvent”>
{ parentData }
</child-component>

child

Vue.component(‘child-component’, {
template: ‘<div><slot/></div>’,
data() {
return {
childData: ‘childData’,
}
},
created() {
this.$emit(‘emit-event’, this)
}
})

parent

new Vue({
el: “#app”,
data: {
parentData: undefined,
},
methods: {
handleEvent({ childData }) {
this.parentData = childData
}
}
})

Check out this fiddle