What is the best way to specify data with brackets in Vuejs? - vue.js

I've a page where field names are of type array.
eg. mapping[map][email_address][type]
Now in Vue, I want to set the default value and I'm doing it as below
new Vue({
el: '#configure',
data: {
mapping: {
map: {
email_address: {
type: 'incoming_field'
}
}
}
}
})
But I get an error in console
[Vue warn]: Property or method "map" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
vue.js:569 [Vue warn]: Property or method "email_address" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
vue.js:569 [Vue warn]: Error in render function:
(found in <Root>)
What is the best way to handle such field names in Vuejs?

As par you code, you have to do:
mapping['map']['email_address']['type']
or
mapping.map.email_address.type

You should rethink your data to not have so many nested objects.
If you are setting a property directly within an object, it is good practice to use Vue.set to ensure you do not break reactivity. Doing this will save you hours of headaches trying to figure out where something broke.
Vue.set(mapping.map.email_address, 'type', value_to_set)

Related

Vue Warn: Property or method is not defined on the instance but referenced during render

I have a model name defined in my Component tag as seen below:
<b-table-column v-if="" field="columnName" v-slot="itemProps">
<SelectableAttribute
:attr-name="props2.row.fieldClass"
:attr-id="itemProps.row.id"
:model-id="props.row.id"
:model-name="NewParticipant"
>
However I receive this error:
[Vue warn]: Property or method "NewParticipant" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
I'm not quite sure how I'm meant to define a model-name, in my props I assume but where? I've attached code below.
export default {
props: {
participants:
{
type: Array,
default: null
},
},
components: {
SelectableAttribute
},
As your error tells you, NewParticipant is not defined. You need to add it to your component as a property in data(), like this:
data() {
return {
NewParticipant: [] // Array for example
}
}
Or else, if you want your prop participants to be the model-name, you need to change it to :model-name="participants".

Vue.js deep watching of computed property using other computed property objects

I am aware of deep watching of properties using the handler in the "watch" section, but I am not seeing how to make vue deep watch in a getter/setter computed property.
Essentially I have something like this, of which vue is not able to observe the changes.
How do I tell vue to observe the changes of "someComputedProperty"?
computed: {
someComputedProperty: {
set (value) {
this.someComputedPropertyObject[this.someOtherObject.id] = value;
},
get () {
return this.someComputedPropertyObject[this.someOtherObject.id];
}
}
}
Thanks in advance,
Erion
If someComputedPropertyObject is a Vue computed property, its value won't be made observable by design (if it creates a new object).
Furthermore, does someComputedPropertyObject have the this.someOtherObject.id property defined upfront? If not, you're creating a new property which Vue cannot observe. Use Vue.set (or this.$set) instead.

Is it possible to pass a reactive property in VueJS?

There is a code I take over from another developer. He used a Vuex property POLL to initialize some components. I wanted to use a different approach - get the object at upper level and pass it as a property downstream to the components. The object is fetched in async method from the backend. I thought that Vue reactivity will initialize real value later. But I get an error:
[Vue warn]: Property or method "poll" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
found in
---> <PollHeading> at src/components/molecules/PollHeading.vue
<CompletePoll> at src/components/organisms/CompletePoll.vue
<Home> at src/views/Home.vue
Home.vue
<Poll v-if="this.$store.getters.LATEST_POLL" :item="this.$store.getters.LATEST_POLL" />
...
created() {
this.$store.dispatch('GET_LATEST_POLL');
},
CompletePoll.vue
<PollHeading :item="item"/>
...
props: {
item: Object,
},
PollHeading.vue
props: {
item: Object,
},
Am I going the wrong direction and the original developer was right? Or is there a way how to fix my approach? He used to do:
PollHeading.vue (I renamed to CompletePoll.vue)
computed: {
poll() {
return {
poll: this.$store.getters.POLL,
};
},
Problem 1)
[Vue warn]: Property or method "poll" is not defined on the instance but referenced during render. means that you have this declared in template block of .vue file, but it's not declared in the script's data property or computed. I don't see that specific .vue file where you use poll variable.
Problem 2) When you use variables in tmeplate blocks, you shouldn't use this .
So instead of this: <Poll v-if="this.$store.getters.LATEST_POLL" :item="this.$store.getters.LATEST_POLL" />
Write: <Poll v-if="$store.getters.LATEST_POLL" :item="$store.getters.LATEST_POLL" />
Problem 3) https://github.com/literakl/mezinamiridici/blob/master/spa/src/components/molecules/PollHeading.vue on this file you use poll in template but you don't have that variable created anywhere. your prop's name is item and not poll. So change poll to item in template block everywhere in that file.

Vue & Vuex splice -- cannot read property of null. Without splice content renders fine

When using Vuex and computed property it returns this error.
Im out of ideas as I tried for several hours to fix it.
it seems the data is not available when it tries rendering the template. The strange thing is, when I don't use splice the error doesn't show up.
error
Vue warn]: Error in render: "TypeError: Cannot read property 'slice' of null"
template
v-for="expert in experts"
:key="expert.name"
#click="goToProfile(expert.id)">
<div class="experts__img">
<LazyImage
:src="avatar(expert.file)"
:srcset="srcset(expert.file)"
:alt="expert.name"
:width="375"
:height="500"
:cover="true"/>
</div>
script
computed: {
experts () {
return this.$store.getters.experts.slice(0,3);
},
If I alternatively use the splice in the frontend section I get the same error
v-for="expert in experts.splice(0,3)"
:key="expert.name"
#click="goToProfile(expert.id)">
The error message indicates that in this code:
computed: {
experts () {
return this.$store.getters.experts.slice(0,3);
},
},
The experts Vuex getter is null. You need to ensure that the getter returns a non-null value at the time when the component is being rendered. Perhaps you didn't initialize some data properly initially? Alternatively you can write defensive code which handles the case when experts is null so you don't trigger the error.
You didn't provide your code for the experts Vuex getter, so I can't give you any further help.
Ok, so figured that I had experts: null in my state, but when I change it to experts:[] the error disappears but then still the content doesn't render at all now.
why doesn't the content show up once loaded? I thought computed with async would render once loaded!??!

How to pass props without creating setters and getters?

In the code below I pass an object to a child component. Vue creates a pair of setter/getter for each property in this object. In other words, it binds each property to make the component reactive. Is there a way to pass an object, like I'm doing here, but without binding? In a real life application I pass an object with ten's of properties and a setter/getter pair is created for each also. This impacts performance a bit. What would you recommend?
Vue.component('child', {
template: '<div>Child!</div>',
props: ['params'],
created () {
console.log(this.params)
}
})
var app = new Vue({
el: '#app',
data () {
return {params: {a: 1, b: 2}}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script>
<div id="app"><child :params="params"></child></div>
No.
I would be highly surprised if converting your properties into getters/setters, which is at the core of Vue's reactivity, is the cause of a performance issue.
The only way to pass a property would be to expose it to Vue at some point, which means that it will be converted to getter/setters when you expose it. In order pass the object without them, you would need to do something like JSON.stringify the object and JSON.parse it on the other side. Then, as soon as you try to use in in your child (by adding it as a data property for example) it's going to be converted into a reactive object again.