Accessing data in vue component - javascript

Im trying to access some data I have binded to a component with no luck. How should I do that?
My component:
export default {
name: 'component-vallingby',
data() {
return {
}
},
created() {},
methods: {}
}
Here's where im rendering it. Offer is an object:
<component-vallingby v-bind="{ offer: offer }"></component-vallingby>

Pass the prop to the component like :order="order". Inside the component vm, list this in props array as a String.
export default {
name: 'component-vallingby',
props: ['offer']
}
Then instantiate your component passing order like this:
<component-vallingby :offer="offer"></component-vallingby>

You need props inside of your export default {} mentioned.
props: ['offer']
You should bind it as
<component-vallingby :offer="offer"></component-vallingby>

Related

object is undefind when passing from blade to vue component using props

I'm trying to pass an array from async method in the controller to a vue component using props through the blade, but I'm getting undefined when I try to console.log it in the vue component, this is my code:
Controller:
public function index(){
$pool = Pool::create();
$pool[] = async(function () {
return Rfm::all();
})->then(function ($output) {
$this->results=$output;
});
await($pool);
return view ("/dashboard", ["data" => $this->results]);
Blade:
<div id="total_customers">
<total-customers :data="{{$data}}"></total-customers>
</div>
Vue component:
export default {
props: ['data'],
data() {
return {
};
},
mounted() {
console.log(this.data);
}
};
I've searched and read somewhere that using async in the controller would be the problem as the object is still empty when it render to vue component, but I'm not sure about that, am i doing it wrong?
Binding props that way might work with strings and integers but doesn't work with array/object data: https://laravel.com/docs/9.x/blade#blade-and-javascript-frameworks
The following should work:
<total-customers :data="{{ Js::from($data) }}"></total-customers>
Addition:
Might want to look into https://inertiajs.com/ if you bind data to vue components in blade a lot, its a nicer way to render vue components with props

How can i type a Vue component created using Vue.extend?

Using Vue with TypeScript, I have created two components using Vue.extend. I now want to access one of them via this.$refs from the other, but i can't access any of its methods via IDE autocomplete if i don't specify its type:
// ChildComponent.vue
export default Vue.extend({
name: 'ChildComponent',
methods: {
test(): void { ... }
}
}
// ParentComponent.vue
<template>
<ChildComponent ref="child_ref" />
</template>
export default Vue.extend({
name: 'ParentComponent',
components: { ChildComponent }
computed: {
child(): InstanceType<typeof ChildComponent> { // This won't work
return this.$refs.child_ref as InstanceType<typeof ChildComponent>;
}
},
methods: {
triggerChildTest(): void {
this.child.test(); // IDE warning: Property 'test' does not exist on type 'CombinedVueInstance'.
}
}
}
Is there any way I can continue to use Vue.extend in a way that will allow me to access data & methods from my components? Can i somehow implement an interface on the resulting component?
I would prefer to keep my codebase using this method than migrate everything to use Vue component classes.

How to loop over components object in the template?

Usually we define in a Nuxt.js component something like this:
<script>
export default {
components: {
// components
}
data() {
return {
// key/value data
}
},
methods: {
// method definitions
}
}
</script>
Is there a way to read the components object as we read data() and methods ?
This is because I have several components and I want to loop on them to refactor parts of my code.
You can get Component data by using $options.
Try this.
created() {
console.log(this.$options.components)
}
it returns an object, keys are the component names, values are the contructors.
codepen - https://codesandbox.io/s/yk9km5m0wv

Pass prop as module name when mapping to namespaced module

I'm trying to pass the store module namespace via props to a component. When I try and map to getters with the prop, it throws this error,
Uncaught TypeError: Cannot convert undefined or null to object
If I pass the name as a string it works.
This Works
<script>
export default {
props: ['store'],
computed: {
...mapGetters('someString', [
'filters'
])
}
}
</script>
This does not work
this.store is defined
this.store typeof is a String
<script>
export default {
props: ['store'],
computed: {
...mapGetters(this.store, [
'filters'
])
}
}
</script>
I used this style utilising beforeCreate to access the variables you want, I used the props passed into the component instance:
import { createNamespacedHelpers } from "vuex";
import module from '#/store/modules/mymod';
export default {
name: "someComponent",
props: ['namespace'],
beforeCreate() {
let namespace = this.$options.propsData.namespace;
const { mapActions, mapState } = createNamespacedHelpers(namespace);
// register your module first
this.$store.registerModule(namespace, module);
// now that createNamespacedHelpers can use props we can now use neater mapping
this.$options.computed = {
...mapState({
name: state => state.name,
description: state => state.description
}),
// because we use spread operator above we can still add component specifics
aFunctionComputed(){ return this.name + "functions";},
anArrowComputed: () => `${this.name}arrows`,
};
// set up your method bindings via the $options variable
this.$options.methods = {
...mapActions(["initialiseModuleData"])
};
},
created() {
// call your actions passing your payloads in the first param if you need
this.initialiseModuleData({ id: 123, name: "Tom" });
}
}
I personally use a helper function in the module I'm importing to get a namespace, so if I hadmy module storing projects and passed a projectId of 123 to my component/page using router and/or props it would look like this:
import { createNamespacedHelpers } from "vuex";
import projectModule from '#/store/project.module';
export default{
props['projectId'], // eg. 123
...
beforeCreate() {
// dynamic namespace built using whatever module you want:
let namespace = projectModule.buildNamespace(this.$options.propsData.projectId); // 'project:123'
// ... everything else as above with no need to drop namespaces everywhere
this.$options.computed = {
...mapState({
name: state => state.name,
description: state => state.description
})
}
}
}
Hope you find this useful.
I tackled this problem for hours, too. Then I finally came up with one idea.
Add attachStore function in a child vue component. A function nama is not important. Any name is ok except vue reserved word.
export default {
:
attachStore (namespace) {
Object.assign(this.computed, mapGetters(namespace, ['filters']))
}
}
When this vue component is imported, call attachStore with namespace parameter. Then use it at parent components attributes.
import Child from './path/to/child'
Child.attachStore('someStoresName')
export default {
name: 'parent',
components: { Child }
:
}
The error you're encountering is being thrown during Vue/Vuex's initialization process, this.store cannot be converted because it doesn't exist yet. I haven't had to work with namespacing yet, and this is untested so I don't know if it will work, but you may be able to solve this problem by having an intermediary like this:
<script>
export default {
props: ['store'],
data {
namespace: (this.store !== undefined) ? this.store : 'null',
},
computed: {
...mapGetters(this.namespace, [
'filters'
])
}
}
</script>
That ternary expression will return a string if this.store is undefined, if it isn't undefined then it will return the value in this.store.
Note that there is also a discussion about this on Vue's Github page here: https://github.com/vuejs/vuex/issues/863
Until Vue formally supports it, I replaced something like
...mapState({
foo: state => state.foo
})
with
foo () {
return this.$store.state[this.namespace + '/foo'] || 0
}
Where namespace is passed to my child component using a prop:
props: {
namespace: { type: String, required: true }
}

How to design a store in Vuex to handle clicks in nested, custom components?

I'm trying to design a store to manage the events of my Vuex application. This far, I have the following.
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const state = { dataRows: [], activeDataRow: {} };
const mutations = {
UPDATE_DATA(state, data) { state.dataRows = data; state.activeDataRow = {}; },
};
export default new Vuex.Store({ state, mutations });
I'm going to have a number of list items that are supposed to change the value of the data in the store when clicked. The design of the root component App and the menu bar Navigation is as follows (there will be a bunch of actions in the end so I've collected them in the file actions.js).
<template>
<div id="app">
<navigation></navigation>
</div>
</template>
<script>
import navigation from "./navigation.vue"
export default { components: { navigation } }
</script>
<template>
<div id="nav-bar">
<ul>
<li onclick="console.log('Clickaroo... ');">Plain JS</li>
<li #click="updateData">Action Vuex</li>
</ul>
</div>
</template>
<script>
import { updateData } from "../vuex_app/actions";
export default {
vuex: {
getters: { activeDataRow: state => state.activeDataRow },
actions: { updateData }
}
}
</script>
Clicking on the first list item shows the output in the console. However, when clicking on the second one, there's nothing happening, so I'm pretty sure that the event isn't dispatched at all. I also see following error when the page's being rendered:
Property or method "updateData" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
I'm very new to Vuex so I'm only speculating. Do I need to put in reference to the updateData action in the store, alongside with state and mutations? How do I do that? What/where's the "data option" that the error message talks about? Isn't it my components state and it's properties?
Why the error
You are getting the error, because when you have <li #click="updateData"> in the template, it looks for a method updateData in the vue component which it does not find, so it throws the error. To resolve this, you need to add corresponding methods in the vue component like following:
<script>
import { updateData } from "../vuex_app/actions";
export default {
vuex: {
getters: { activeDataRow: state => state.activeDataRow },
actions: { updateData }
},
methods:{
updateData: () => this.$store.dispatch("updateData")
}
}
</script>
What this.$store.dispatch("updateData") is doing is calling your vuex actions as documented here.
What/where's the "data option"
You don't have any data properties defined, data properties for a vue component can be used, if you want to use that only in that component. If you have data which needs to be accessed across multiple components, you can use vuex state as I believe you are doing.
Following is the way to have data properties for a vue component:
<script>
import { updateData } from "../vuex_app/actions";
export default {
date: {
return {
data1 : 'data 1',
data2 : {
nesteddata: 'data 2'
}
}
}
vuex: {
getters: { activeDataRow: state => state.activeDataRow },
actions: { updateData }
},
methods:{
updateData: () => this.$store.dispatch("updateData")
}
}
</script>
You can use these data properties in the views, have computed properies based on it, or create watchers on it and many more.

Categories

Resources