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

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".

Related

Ignore undefined props

I am passing an object like this into a component:
obj = {
prop1: 1,
prop2: 2,
prop3: 3
}
<my-component :data="obj"></my-component>
the component only has these two defined, by design, because I want to ignore what is not defined:
props: {
prop1: Number,
prop2: Number
}
what's happening is when the component is rendered, the root node looks like this with the undefined prop placed like an attribute?!:
<div prop3="3">
...
</div>
I don't want undefined props to be de-structured by the component and definitely don't want them to rendered in the root element. I want them to be ignored. Is there a flag or some setting to say ignore all undefined props?
Please don't say why I would ever need this. I do because these objects are built somewhere else and don't want to create new subset objects just for this purpose.
You can use:
props: {
prop1: Number,
prop2: Number
},
inheritAttrs: false
This will tell Vue to not add additional props to the element as attribute but those props will instead be stored in $attrs, so you could access your prop using this.$attrs.prop3
See https://vuejs.org/guide/components/attrs.html#disabling-attribute-inheritance

[Vue warn]: Property or method "Boston" is not defined on the instance but referenced during render

I'm setting up some props, as shown below.
Component 1 (Parent):
<template>
<div>
<span>{{agency1}}</span>
<span>{{workstation}}</span>
</div>
</template>
<script>
export default {
name: "work-station-view",
props: {
agency1: {
type: String
},
workstation: {
type: Number
}
},
data() {
return {};
}
};
</script>
Component 2 (Child):
<template>
<WorkStationView :workstation="1.1" :agency1="Boston" />
</template>
The workstation prop renders fine, but the agency1 prop doesn't show up at all. I get this message from Vue in the console:
[Vue warn]: Property or method "Boston" 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.
I checked the docs, as it says to define it in data(), so I did a combination of all of these (probably more) to no avail:
// attempt 1
data() {
agency1 = this.agency1;
return {};
}
// attempt 2
data() {
return {
agency1 = this.agency1;
};
}
// attempt 3
data() {
return {
agency1: '';
};
}
If I use a number value for agency1 (<WorkStationView :workstation="1.1" :agency1="3" />), it shows! What is going on?
If you're using an inline string, you should skip the : or quote your string.
The : is short-hand for v-bind and is expected to be used with variables that you're binding when passing attributes from the parent component to the child. In this case, you don't have a variable called Boston in the parent context, and hence the error from Vue.
If all you want to do is use a constant string like Boston, just use it like
<WorkstationView :workstation="1.1" :agency="'Boston'" />
Alternatively, it would've also worked if you did the following:
<WorkstationView :workstation="1.1" agency="Boston" />
:agency1="Boston" is shorthand for v-bind:agency1="Boston". It attempts to bind a data property named Boston, but you don't have one defined. :agency1="3" works because 3 is a literal. If you were attempting to assign the literal string "Boston" to agency1, don't use the preceding colon:
<!--
<WorkStationView :agency1="Boston">
--> <!-- DON'T DO THIS -->
<WorkStationView agency1="Boston">

vuejs pass model from parent component to children component and allow mutation

Currently I have a vue-multiselect component which requires a v-model.
I want to wrap this component so that I can build one single-select component and one multi-select component.
While working on the single select component I encountered the following warning
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "model"
They are right but in my case I really need to change the value from the parent (like I replace my single-select code with the vue-multiselect code) component and I also do not want this warning.
Here is the code for my component:
Vue.component('single-select', {
props: {
model: {
required: true
}
}
template: '<multiselect\n' +
' v-model="model"\n' +
...>\n' +
...
'</multiselect>'
});
One solution would be to pass a function as a model parameter and return the field from the parent but I really hope for a better solution.
Vue has a shortcut for 2 way binding called .sync modifier.
How it works in your case:
add .sync when you pass model as prop
<single-select :model.sync="..."></single-select>
emit an update:model in the child's input event
Vue.component('single-select', {
props: {
model: {
required: true
}
},
template: `<multiselect :value="model" #input="$emit('update:model', $event)"> </multiselect>`
});
Just give the internal model reference a different name, and the in the Vue component's data function map it manually:
Vue.component('single-select', {
props: {
model: {
required: true
}
},
data: function() {
return {
singleSelectModel: this.model
};
}
template: '<multiselect v-model="singleSelectModel"></multiselect>';
});
This is of course, assuming that you do not want to mutate the parent data, but simply making a copy of model and giving the child component the freedom to change it whenever it wants.
If what you want is to also update the parent data from the child, you will have to look into emitting events from the child and listening in the parent.

Vue.js: property or method is not defined on the instance, but it is

I have a Vue.js component that looks like this:
<!-- MyComponent.vue -->
<script>
export default {
render: () {
return;
},
methods: {
foo() {
alert('hi');
},
},
};
</script>
And then my HTML looks like this:
<my-component #click="foo" />
When I run this I get an error:
Property or method "foo" 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 can't seem to understand what I'm doing wrong here -- all the other SO questions about this error seem to be caused by scoping issues, but I'm just dealing with a simple component.
foo would need to be defined in the component using my-component, not in my-component itself.
Also, you'd need to do #click.native, unless you're specifically $emiting an event called click in my-component.
If you were to use #click="foo" inside of this component on an html element it would work like you expect (a #click on a component needs .native).

Passing data to Vue.js component

I am creating a component and want to pass two properties (item & brokerageID) to the component. Here is the HTML code:
{{brokerageID}}
<holiday-component v-bind:item="item" v-bind:brokerageID="brokerageID" testID="45" ></holiday-component>
Here is the code for 'holiday-component'
Vue.component('holiday-component', {
props: ['item',
'brokerageID',
'testID',
],
data () {
return {
holidaysData: [],
showHolidays: false,
}
},
methods: {
getHolidays(contactID) {
....
},
template: <div> {{testID}} {{item.contactName}} {{brokerageID}}
....
The 'item' property is getting passed to the component (item.contactName is displayed correctly in the component template. However, somehow, brokerageID (property of the Vue object) is not getting passed. This property exists which is confirmed as {{brokerageID}} used above the component in HTML displays value. But, within the component template, brokerageID is not available. Also, the testID property passed to the component is not displayed.
Could someone please advise, what is wrong in my implementation that I am unable to use brokerageID in my component?
See Vue's docs about prop naming https://v2.vuejs.org/v2/guide/components.html#camelCase-vs-kebab-case
In this instance, using v-bind:brokerage-id and v-bind:test-id should do the trick.