Change data between few router-view - vue.js

I have two components, and can't pass data from one to another component
at first router-view have
data() {
return {
mode: true,
}
},
<input type="checkbox" class="switch-mode" v-model="mode" #change="$root.$emit('switch-mode', mode)">
and other is
data() {
return {
filter: {
mode: false,
order: 'DESC'
},
}
},
mounted() {
this.$root.$on('switch-mode', function (EventGrid) {
console.log('Grid mode is '+EventGrid); //this works it return true,false
this.filter.mode = EventGrid; // not working this.filter is undefined"
})
},

This happens because your function doesn't know what this is, you should explicitly tell it to use your component:
mounted() {
this.$root.$on(
'switch-mode',
(function (EventGrid) { ... }).bind(this)
)
}
Or, more effectively and modern, use an arrow function:
mounted() {
this.$root.$on('switch-mode', (EventGrid) => { ... })
}

Related

Vue dynamic component template not working for promise

<template>
<component :is="myComponent" />
</template>
<script>
export default {
props: {
component: String,
},
data() {
return {
myComponent: '',
};
},
computed: {
loader() {
return () => import(`../components/${this.component}`);
},
},
created() {
this.loader().then(res => {
// components can be defined as a function that returns a promise;
this.myComponent = () => this.loader();
},
},
}
</script>
Reference:
https://medium.com/scrumpy/dynamic-component-templates-with-vue-js-d9236ab183bb
Vue js import components dynamically
Console throw error "this.loader() is not a function" or "this.loader().then" is not a function.
Not sure why you're seeing that error, as loader is clearly defined as a computed prop that returns a function.
However, the created hook seems to call loader() twice (the second call is unnecessary). That could be simplified:
export default {
created() {
// Option 1
this.loader().then(res => this.myComponent = res)
// Option 2
this.myComponent = () => this.loader()
}
}
demo 1
Even simpler would be to rename loader with myComponent, getting rid of the myComponent data property:
export default {
//data() {
// return {
// myComponent: '',
// };
//},
computed: {
//loader() {
myComponent() {
return () => import(`../components/${this.component}`);
},
},
}
demo 2

Why does Vuetify Autocomplete not selecting the data being set?

I use Vuetify autocomplete as a reusable component to display a list of jobs in key/value pairs. In creating record, the component works fine but when editing where data should be filled in, the data has the value but not showing on the component.
JobDropdownSelector.vue:
................................................................................................................................................
<template>
<v-autocomplete
v-model="job"
label="Job Designation"
item-value="id"
item-text="name"
return-object
:items="jobs"
#change="onChange"
>
</v-autocomplete>
</template>
<script>
export default {
props: {
selectedJob: {
type: Object,
default: null
}
},
data() {
return {
jobs: [],
job: null
};
},
methods: {
getDataFromApi() {
axios.get("api/jobs")
.then(response => {
this.jobs = response.data.data;
})
.catch(error => {
console.log(error);
reject();
});
},
onChange(e) {
this.job = e;
this.$emit("onChange", e);
}
},
watch: {
selectedJob: {
deep: true,
immediate: true,
handler(newValue, oldValue) {
this.job = newValue;
}
}
},
mounted() {
this.getDataFromApi();
}
};
</script>
EditForm.vue:
................................................................................................................................................
<template>
<div>
<JobDropdownSelector
v-model="job"
:selectedJob="job"
#onChange="onChangeJob"
>
</JobDropdownSelector>
</div>
</template>
<script>
import JobDropdownSelector from "../components/JobDropdownSelector";
export default {
components: {
JobDropdownSelector
},
data() {
return {
job: null
};
},
methods: {
onChangeJob(e) {
this.job = e;
},
getInitialJob() {
axios.get("api/jobs/22").then(response => {
this.job = response.data.data;
});
}
},
mounted() {
this.getInitialJob();
}
};
</script>
Display
Console
It looks like you overriding job twice: on the onChangeJob method and via v-model on JobDropdownSelector.
You can try use input event to update modek instead of emitting additional event.
JobDropdownSelector.vue
methods: {
onChange(e) {
// You don't need set job because it's connected via v-model.
// this.job = e;
this.$emit("input", e);
}
}
This will cause that job in EditForm.vue should update automatically after dropdown change.

VueJS how to filter a mapgetter array

I have the following mapgetter inside a component:
props: {
hideSidebarText: { type: Boolean, default: false }
},
computed: mapGetters({
menuItems: 'menuTypes',
}),
This computed property is used to create a list:
<div
class="sidebar"
v-for="item in menuItems"
:key="item.name"
>
The list has property hidden that i want to filter to show only the elements where hidden is false.
How can I extend the mapGetter inside computed section so I can do the filter in my component something like this:
computed: {
menuItems: function() {
return this.menuItems.filter(function(u) {
return u.hidden == false
})
}
I ended with the following solution, dont know if is the right way to do it but make sense to me:
computed: {
...mapGetters({
menuItems: 'menuTypes'
}),
filteredMenuItems: function() {
return this.menuItems.filter(function(i) {
return i.hidden == false;
});
}
},

VueJS: How to access computed values in render function

I currently have a component with this render function:
render(createElement, context) {
return createElement(
'div', {
'class': 'sliced'
},
[
createElement('div', {
'class' : 'sliced-inner',
'style' : context.style
}
)
]
)
},
and I've added functional: true. The "style" is a computed value, but it doesn't seem to get passed with the context object. Is there any way to access computed values in a Vue render function?
A functional component has no state, so a computed property is redundant. In the following example I'm creating a header component that toggles between foo and bar when clicked:
Vue.component('message', {
render (createElement) {
return createElement('h1', {
on: {
click: event => {
return this.foo = !this.foo
}
}
}, this.fooBar)
},
computed: {
fooBar() {
return (this.foo) ? 'foo' : 'bar'
}
},
data(){
return {
foo: true
}
}
});
As you can see the header value is based on a computed, and it works fine because it is not a functional component so can have state: https://jsfiddle.net/hwbbukvd/
If I make that a functional component by adding functional: true, then it does not work because it's display relies on the component having state: https://jsfiddle.net/cygjdjru/
See: https://v2.vuejs.org/v2/guide/render-function.html#Functional-Components
In your case, if you aren't looking for style to be reactive, then I'm guessing you just want to pass a prop
Vue.component('message', {
functional: true,
render(createElement, context) {
return createElement('h1', context.props.foo)
},
props: {
foo: {
required: true
}
}
});
See: https://jsfiddle.net/qhzh0a2c/

Vue.js watcher not executed when manually setting value

I have this Vue component:
methods: {
...
toggleTyping: function () {
this.composing = !this.composing;
},
...
},
data: function () {
return {
composing: false,
};
},
watch: {
composing: function (val) {
alert(val);
}
}
When I execute toggleTyping() the watcher is not called. I'm very new to vuejs.
Everything you are showing works. The error must lie elsewhere.
new Vue({
el:"#app",
methods: {
toggleTyping: function() {
this.composing = !this.composing;
},
},
data: function() {
return {
composing: false,
};
},
watch: {
composing: function(val) {
alert(val);
}
}
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app">
<button #click="toggleTyping()">Toggle</button>
</div>
Well, thanks everyone, the problem was really weird, I had a function also declared in the body of the component called type (it was making a typing animation, so I choose that name). When I renamed that function it started to work!
I put the failing code to clarify and help anyone else:
....
,
type : function () {
...
},
watch: {
composing: function (val) {
alert(val);
//Never called!
}
}