How to get state item via props in vuejs with vuex - vue.js

I'm sorry for my bad english.
I've fromSelected props in vue. I want to get state selected item via props value.
I've from component.
<template>
<h1>this.$store.state.fromSelected</h1>
</template>
<script>
export default {
props: ['fromSelected']
}
</script>
in vuex state like this
const state = {
'one': null,
}
I use my from component in root component like this
<from from-selected="one"></from>
When I use this.$store.state.fromSelected I want to get this.$store.state.one in from component.

It seems that the problem you are facing has to do with the flow of the data in Vue and Vuex. There are two different problems that need to be addressed here:
Problem nr. 1 - Data Flow and Scopes:
In your template code: <h1>this.$store.state.fromSelected</h1> you are trying to access the component property in the Vuex state. It will not exist there as it only exists in the components local scope. Here is an illustration of how the flow of data would work:
Problem nr. 2 - Static and Dynamic Props:
In the line <from from-selected="one"></from> you are not prepending the property with a colon and therefore the prop will be considered a string literal and not an expression where you could pass in a variable. Read more here: https://v2.vuejs.org/v2/guide/components-props.html#Static-and-Dynamic-Props
Solution:
The solution would be to pass in the value from the Vuex state as a dynamic property to the component; like this:
// Javascript
const store = new Vuex.Store({
state: {
one: "This comes from the Vuex state"
},
})
new Vue({
el: "#app",
store: store,
components: {
from: {
template: '<span>{{ fromSelected }}</span>',
props: ['fromSelected']
}
}
})
// Template
<div id="app">
<from :from-selected="$store.state.one"></from>
</div>
Try it here: https://jsfiddle.net/vngrcu5v/

Ifound. I must write like this.
// From.vue component
<template>
<span>{{this.fromSelected}}</span>
</template>
<script>
export default {
props: ['fromSelected']
}
</script>
// Root component
import from from 'from';
<from :from-selected="this.$store.state.one"></from>
// State
export default {
'one': null,
}

Did you try to put fromSelected with same syntax?
<from fromSelected="one"></from>

Related

Access component parameters inside caller component

I have a component which I call inside another component as:
COMPONENT 1
<template>
<FiltersComponent />
</template>
export default Vue.extend({
components: { FiltersComponent }
)}
So, this FiltersComponents have some parameters I want to access into my component one
COMPONENT 2 DATA
data() {
return {
TestList: [] as string[],
Test2List: null as string[] | null,
}
},
How can I access that TestList and Test2List inside COMPONENT 1?
There are multiple possibilities: If one component is a child component or sibling of the other, you might want to take a loop at props (passing data down) and events (passing data up). Otherwise, if they are not siblings or children, you can use a store like vuex.
To use the docs example:
vue entry point: (e.g., app.js):
import { createApp } from 'vue'
import { createStore } from 'vuex'
// Create a new store instance.
const store = createStore({
state () {
return {
someProperty: 'someValue'
}
},
mutations: {
update (state, value) {
state.someProperty = value
}
}
})
const app = createApp({ /* your root component */ })
// Install the store instance as a plugin
app.use(store)
In your component's script-section:
this.$store.commit('update', 'YOUR_VALUE')
Other component:
const val = this.$store.state.someProperty
However, this is only a very basic example. You should definitely check out the docs, especially the sections about state, getters and mutations.
Always store the state as high in the component tree as you need, meaning that if you need these lists inside component 1, store them there. Then, you can use props and events to access and update the data inside component 2.
Alternatively, you can use a centralized store like Vuex.
You can achieve the same using ref,
Check the below example
<template>
<FiltersComponent ref="childComponent" /> <!-- Adding ref over here -->
</template>
export default Vue.extend({
components: { FiltersComponent }
)}
then in any of your methods or mounted section in Component 1. You can access Component2 data like
this.$refs.childComponent.TestList
or
this.$refs.childComponent.Test2List
So simple isn't it? ;)

Dynamically update props

As simplified below, my app has a template with a custom component.
The data is passed from Template A to custom component as props (":list")
Template A:
<template>
...
<custom-component
v-for="list in listGroup"
:key="list.id_list"
:list="list"
/>
</template>
<script>
export default {
data() {
return {
listGroup: []
};
},
components: {
'custom-component':require("...").default
}
</script>
The custom component
<template>
...
</template>
<script>
export default {
props:["list];
...
}
</script>
Problem to solve:
A new item is added to the list sent as props.
I need the list (:list="list") to be dynamically updated so that the props in the custom component automatically reflect that update.
Thanks.
There are two ways to achieve that one way is to use a state management library(Vuex is recommended) the other is to use events.
Here is an example of using events:
create a file event-bus.js with the following content
import Vue from "vue";
export const EventBus = new Vue();
then in your component where you want to update list use this EventBus.$emit('eventName', data);
remember to import event-bus file
the listen to the event in the other component
EventBus.$on('eventName', function (details) {
//update list here
});

How to bind a local component's data object to an external component

how do you use a local component's data attriutes to bind an external component's v-model
for example i have this component
<publish-blog>
<VueTrix v-model="form.editorContent">
</publish-blog>
so the form.editorContent there refers to the publish-blog component's form.editorContent inside data, how do I do that ?
You can pass a prop to the publish-blog component.
This would be what ever page or component you are using the publish blog on, though to be honest I'm not sure why you would not just put the VueTrix component inside of the publish-blog component.
This would be on what ever page/component you are wanting it on.
<template>
<PublishBlog :trix="trix">
<VueTrix v-model="trix" />
</PublishBlog>
</template>
<script>
import PublishBlog from './PublishBlog.vue';
export default {
components: {
PublishBlog,
},
data() {
return {
trix: '',
};
},
};
</script>
and inside of the publish blog component make the form.editorContent the prop passed or a default value.
But without a global store/state you are stuck with props.
UPDATE: Showing what a publish blog component might look like
PublishBlog.vue
<template>
<section>
what ever goes here.
<slot />
</section>
</template>
<script>
export default {
name: 'PublishBlog',
props: {
trix: {
type: String,
default: '',
},
},
data() {
return {
form: {
editorContent: this.trix
},
};
},
};
</script>

Sharing data between components in vue.js

I got an array of data in one component which I want to access in another component but cannot get it right
My idea was to just import component one in component two and thought I could access the data in that way but it didnt work.
here is what I got so far ...
Component 1:
export default {
data() {
return {
info: [
{
id: 1,
title: "Title One"
},
{
id: 2,
title: "Title Two"
},
Component 2:
<template>
<div>
<div v-for="item in info" v-bind:key="item.id">
<div>{{ item.title }} </div>
</div>
</div>
</template>
<script>
import ComponentOne from "../views/ComponentOne ";
export default {
components: {
ComponentOne
}, But after this I am a bit lost
Can anyone point my to the right direction it would be very much appreciated!
In order to access shared data, the most common way is to use Vuex. I'll get you going with the super basics with a module system as it does take a little reading.
npm install vuex --save
Create new folder called store in the src directory.
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import example from './modules/example'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
example // replace with whatever you want to call it
}
})
src/main.js
// add to your imports
import store from './store/index'
...
// Change your Vue instance init
new Vue({
router,
store, // <--- this bit is the thing to add
render: h => h(App)
}).$mount('#app')
/src/store/modules/example.js
// initial state
const state = {
info: []
}
// getters
const getters = {}
// actions
const actions = {
}
// mutations
const mutations = {
set (state, newState) {
state.info.splice(0)
state.info.push.apply(state.info, newState)
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
To update the store when you get info, from any component you can use this.$store.commit('example/set', infoArray) where the first parameter follows the pattern of module name/mutation function name, and the second parameter is the 'new state' that you want updated.
To access the data from the store, you can access it from your components as a computed property:
computed: {
info () {
return this.$store.state.example.info
}
}
Obviously you can use getters and actions and other stuff, but this will get you going and you can read up and modify the Vuex store once you get comfortable and understand how it works.
Let's say if you do not want to use any other state management like vuex then you can share with the use of mixins.
Well, you can achieve it with the use of Vue.mixins.
Mixins are a flexible way to distribute reusable functionalities for Vue components. A mixin object can contain any component options. When a component uses a mixin, all options in the mixins will be “mixed” into the component’s own options.
Mixins official docs
Hope this helps!

How to catch events across multiple child Vue components

I am building a form framework in vue. I have components for each field type. Each field type component uses this.$emit to communicate changes with the parent component.
I am able to trigger events in the parent component using v-on directives as follows:
<template>
<div v-if="fieldsLoaded">
<form-select :field="fields.title" v-on:updated="validate" ></form-select>
<form-input :field="fields.first_name" v-on:updated="validate" ></form-input>
</div>
</template>
However, I don't want to have to manually specify that every component should trigger the validate method individually.
How can I have the parent component listen for the updated emit across all its child components?
Edit: I'm looking for something like the below, though $on only catches emits that occur within the same component, rather than its children
created: function(){
this.$on('updated',validate)
}
The best way is to use event bus or even better in my opinion vuex.
For the first case take a look here
For the second here
With event bus you can emit an event, and listen to that event whenever you want(at parent,child even in the same component)
Vuex It serves as a centralized store for all the components in an application and you can have properties in that store,and you can use and manipulate them.
Example with event Bus:
main.js:
import Vue from 'vue'
import App from './App.vue'
export const eventBus = new Vue();
new Vue({
el: '#app',
render: h => h(App)
})
User Component
<template>
<button #click="clicked">Click me to create event</button>
</template>
<script>
import { eventBus } from './main'
export default {
name: 'User',
methods: {
clicked() {
eventBus.$emit('customEvent', 'a text to pass')
}
}
}
</script>
Admin component
<template>
<p>The message from event is: {{message}}</p>
</template>
<script>
import { eventBus } from './main'
export default {
name: 'Admin',
data: () => ({
message: ''
})
created() {
eventBus.$on('customEvent', dataPassed => {
this.message = dataPassed
}
}
}
</script>
Take a look to this tutorial to learn Vuex
For your case you can use v-model like following:
<template>
<div v-if="fieldsLoaded">
<form-select v-model="fields.title" :validate="validate" ></form-select>
<form-input v-model="fields.first_name" :validate="validate" ></form-input>
</div>
</template>
v-model is essentially syntax sugar for updating data on user input events.
<input v-model="something">
is just syntactic sugar for:
<input v-bind:value="something" v-on:input="something = $event.target.value">
You can pass a prop : value in the child components, and before changing input field call a function to validate which is also passed as a prop.
Vue.component('form-select', {
props: ['options', 'value', 'onChange', 'validate'], //Added one more prop
template: '#your-template',
mounted: function () {
},
methods: {
change (opt) {
if (this.validate !== undefined) {
var isValid = this.validate(this.value)
if(!isValid) return;
}
this.$emit('input', opt)
},
},
})