I'm learning vue.js and used vue-cli to setup a new project. Now I tried adding a method to a component but something is wrong:
<template>
<div>
<div v-for="task in $state.settings.subtasks">
<input type="text" v-model="task.text">
<input type="text" v-model="task.assignedTo">
<input type="button" v-on:click="removeTask(task)">
</div>
</div>
</template>
<script>
export default {
name: 'settings',
methods:{
removeTask:function(task){
console.log("remove task");
}
}
}
Clicking the button should call the removeTask function but it just outputs an error in the console:
[Vue warn]: Property or method "removeTask" 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
---> <Settings> at src/views/Settings.vue
<App> at src/App.vue
<Root>
What is wrong here?
When I went back to my question I noticed I was missing the </script> end tag. Adding that solved my problem.
Related
I am using Vue3 and facing problem that I cannot bind nested property to v-model correctly.
Here is source code:
Template:
<div id="app">
<span>{{level1.level2.level3}}</span> <br/>
<span>{{level1['level2']['level3']}}</span> <br/>
<input v-model="level1.level2.level3" /> <br/>
<input v-model="level1.level2['level3']" /> <br/>
<input v-model="level1['level2']['level3']" />
</div>
JS
Vue.createApp({
data() {
return {
level1: {
level2: {
level3: "val"
}
}
}
},
methods: {}
}).mount("#app")
<input v-model="level1.level2.level3" /> bind works
<input v-model="level1.level2['level3']" /> bind works
but <input v-model="level1['level2']['level3']" /> bind fails
The console warning said
"[Vue warn]: Template compilation error: v-model value must be a valid JavaScript member expression.
What's the reason level1['level2']['level3'] not binding to v-model correctly? I think it's a valid js expression.
Here is online fiddle
It looks like this is an issue with Vue itself, not with your code. It also seems that this issue has been fixed in a commit just over a week ago.
So if you're on Vue <=3.1.1 (a.k.a any version but the current GitHub master branch), your only real solution here would be to rework how you access properties, wait for a Vue update, or depend directly on the GitHub repository's master branch (not a great idea in general, so only do this if you need this notation and you need it right now).
I've been getting null when I try to see what's inside an id with document.getElementById. Part of the code is below:
<input-layout v-if="edit" label="Status" class="grayout">
<u-select v-model='test.status' :options="testStatus" tabindex="14" class="grayout" id="testStatusDropDown"/>
</input-layout>
<input id="input1" type="checkbox">
Note that, v-if="edit" results in true.
In the mounted life cycle hook I have:
mounted () {
this.$nextTick(function (){
console.log(document.getElementById("input1"))
console.log(document.getElementById("testStatusDropDown"))
})
},
Originally I didn't have the console.log statements in the mounted method which resulted in null for both input1 and testStatusDropDown. I understand that because both elements do not exist yet when that part of the code runs. So then I moved them into the mounted method, now, I can see <input id="input1" type="checkbox"> but for the second log statement I get null.
I went to the vue js mounted api docs, which can be found here: https://v2.vuejs.org/v2/api/#mounted. From what I can see is that mounted does not guarantee all child components have been mounted so I need to use this.$nextTic inside the mounted method. However, even after adding this.$nextTick I'm still having the same issue where document.getElementById("testStatusDropDown") results in null when I expect it to be <u-select v-model='test.status' :options="testStatus" tabindex="14" class="grayout" id="testStatusDropDown"/>.
Is my expectation incorrect? What do I need to change such that document.getElementById("testStatusDropDown") does not return null?
Use ref to reference an element in vuejs.
<input id="input1" ref="input1" type="checkbox">
and in mounted access it using:
this.$refs.input1
I'm using a v-if in my parent to conditional render a child component.
Even when the child should not render the mounted function still gets executed and results in an error in console.
How does one makes sure the child component is rendered when launching a method when the child component is rendered.
In my case I'm using an autofocus:
mounted: function () {
// Autofocus input on load.
this.$nextTick(() => this.$refs.input.focus());
},
Error in nextTick: "TypeError: _this.$refs.input is undefined"
console.log(this.$refs.input) gives the object:
<input class="form-control" data-v-661f7e55="" type="text" autocomplete="off">
Try this.
<input class="form-control" ref="input" type="text" autocomplete="off">
mounted(){
this.$nextTick(() => this.$refs.input.focus())
}
This is working fine for me.ref is used to register a reference to an element or a child component.
This is my very first code in Vue.js. I am following a simple online tutorial. After installing the application using the vue-cli, I created a simple component
Test.vue which contains a simple input control bound to the message property of my model:
Test.vue
<template>
<div
<input
type="text"
v-model="message"/>
<br/>
<p>The value of the input is: {{ message }}</p>
</div>
</template>
<script>
export default {
data:{
message: 'My name'
}
};
</script>
<style>
</style>
Then I load this component inside the <App />. But when I write a text inside the input box, the <p> element is not updated...
What am I doing wrong? This looks pretty straightforward. Thanks you for your suggestions and pointing me to the right direction.
In a component, data must be a function.
export default {
data(){
return {
message: 'My name'
}
}
};
Also, your template is missing a > in the first div, but I'm guessing that happened writing the question.
<template>
<div>
<input
type="text"
v-model="message"/>
<br/>
<p>The value of the input is: {{ message }}</p>
</div>
</template>
I have something like this in my parent scope:
<form-error :errors="errors"></form-error>
<textarea class="form-control" name="post" cols="30" rows="8" #keydown="errors.clear('post')" v-model="post"></textarea>
Note the #keydown event, where I am clearing out the errors, by calling
method on a class.
With :errors="errors" I am passing instance of the below Errors class,
into <form-error> child component:
class Errors {
constructor() {
this.errors = {};
}
get(field) {
if (this.errors[field]) {
return this.errors[field][0];
}
}
clear(field) {
delete this.errors[field];
}
has(field) {
return this.errors.hasOwnProperty(field);
}
}
And in <form-error> child component I have this:
<template>
<div v-if="errors.has('post')" class="alert alert-danger" v-text="errors.get('post')"></div>
</template>
<script>
export default {
props: ['errors']
};
</script>
Now, while v-text="errors.get('post')" works fine, and I am getting error
displayed, the v-if="errors.has('post')" part doesn't work at all.
I am assuming errors is passed the right way as props, otherwise that
errors.get('post') wouldn't work.
Question is, why when parent triggers that #keydown event, and I see the
errors object is being emptied properly (Vue addon for chrome), the v-if
part doesn't update, thus hiding the div?
As you can see, the <FormError> child component is being updated to reflect the change in errors when I start typing, but still v-if doesn't trigger.
Edit
What's even more confusing, docs say:
Note that objects and arrays in JavaScript are passed by reference, so if the
prop is an array or object(as in my case), mutating the object or array itself inside the
child will affect parent state.
Although of course I am not mutating the object from with in my child, but the
important part is that object changes in parent should be reflected in child.
Are you getting any error. As I can see Map.has has poor support in browsers. You can try using any of following alternatives:
post in errors
<template>
<div v-if="'post' in errors" class="alert alert-danger" v-text="errors.get('post')"></div>
</template>
errors['post']
<template>
<div v-if="errors['post'] !== undefined" class="alert alert-danger" v-text="errors.get('post')"></div>
</template>