I don't know why but this error Property 'myfunc' was accessed during render but is not defined on instance is keeps on showing.
I am sharing my Html and js code.
const ListRenderingApp = {
data() {
return {
todos: [
{ text: 'Learn JavaScript' },
{ text: 'Learn Vue' },
{ text: 'Build something awesome' }
]
}
},
method : {
myfunc(){
console.log('drats')
}
}
}
Vue.createApp(ListRenderingApp).mount('#list-rendering')
And the Html files code is
<div id="list-rendering" class="demo">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
<button v-on:click="myfunc"> Click me</button>
</div>
I am very new to Vue.js. So, if anyone can please help me with this question.
I understood the error. And came up with the solution as well.
Firstly, In the ListRenderingApp after the data function. It should be methods. And secondly, in the console.log() statement it should be console.log(this.todos).
Working Demo :
new Vue({
el: '#app',
data: {
todos: [
{ text: 'Learn JavaScript' },
{ text: 'Learn Vue' },
{ text: 'Build something awesome' }
]
},
methods : {
myfunc() {
console.log('drats')
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
<button v-on:click="myfunc"> Click me</button>
</div>
Related
I am looking for a way to group objects in different DIV's with a header text.
The following allows me to group 'category 'bla1' but I'd like to have categories 'bla2' and 'bla3' to be grouped as well. The number of categories isn't fixed and can be less or more.
This is what I have so far: JSFIddle
<div id="app">
<h2>Todos:</h2>
<ol>
<div v-for="todo in todos">
<p v-if="todo.category == 'bla1'">
{{ todo.text }}
</p>
</div>
</ol>
</div>
new Vue({
el: "#app",
data: {
todos: [
{ text: "Learn JavaScript", category: "bla1" },
{ text: "Learn Vue", category: "bla2" },
{ text: "Play around in JSFiddle", category: "bla1" },
{ text: "Build something awesome", category: "bla3" }
]
}
})
resulting is:
Todos:
Learn JavaScript
Play around in JSFiddle
But the desired result is:
Todos:
bla1
Learn JavaScript
Play around in JSFiddle
bla2
Learn Vue
bla3
Build something awesome
Create a computed property to group you list by category, and then do a nested loop in your template:
computed: {
groupedToDos() {
let groupedToDos = {};
this.todos.forEach(todo => {
if (todo.category in groupedToDos) {
groupedToDos[todo.category].push(todo)
}
else {
groupedToDos[todo.category] = [todo]
}
})
return groupedToDos
}
}
And then in your template:
<div id="app">
<h2>Todos:</h2>
<ol>
<div v-for="(todos, key) in groupedToDos">
<h3>{{ key }}</h3>
<p v-for="todo in todos">
{{ todo.text }}
</p>
<br />
</div>
</ol>
</div>
jsfiddle
The computed property approach is the best IMHO.
computed:{
sampleComputed(){
if (this.sampleData.value === "Sample 1") return "Sample 1 Value"
if (this.sampleData.value === "Sample 2") return "Sample 2 Value"
return "Sample 0 Value"
}
}
Above sample code can be used with Switch case also if you have more than 5 conditions, or even using object literals to fetch returning data to improve time complexity.
However, if you want you can add more v-if inside the template itself, but it is not advisable to do so since you should focus on separating complex logic from template as a best practice.
References: Proper way to express switch statement with Vue data bindings
I want to change the status of Tasks when a particular method is called. But The problem is I cannot get the index of the particular item of the array to change its status.
This is my HTML:
<div class="main" id="my-vue-app">
<ul>
<li v-for="task in completeTask">
{{ task.description }} <button #click="markIncomplete">Mark as Incomplete</button>
</li>
</ul>
<ul>
<li v-for="task in incompleteTask">
{{ task.description }} <button #click="markComplete">Mark as Complete</button>
</li>
</ul>
</div>
And this is my Vue:
<script>
new Vue(
{
el: '#my-vue-app',
data:
{
tasks: [
{description:'go to market', status: true},
{description:'buy book', status: true},
{description:'eat biriani', status: true},
{description:'walk half kilo', status: false},
{description:'eat icecream', status: false},
{description:'return to home', status: false}
]
},
computed:
{
incompleteTask()
{
return this.tasks.filter(task => ! task.status);
},
completeTask()
{
return this.tasks.filter(task => task.status);
}
},
methods:
{
markComplete()
{
return this.task.status = true;
},
markIncomplete()
{
return this.task.status = false;
}
}
}
)
</script>
I need make use of markComplete() and markIncomplete() but the problem is I couldn't find the way to get the index of current element to change its status.
You could get the index by declaring a second argument at the v-for:
<li v-for="(task, index) in incompleteTask">
{{ task.description }} <button #click="markComplete(index)">Mark as Complete</button>
</li>
methods:
{
markComplete(index)
{
return this.tasks[index].status = true;
},
But a, maybe simpler, alternative is to simply **pass the `task` as argument**:
<li v-for="task in incompleteTask">
{{ task.description }} <button #click="markComplete(task)">Mark as Complete</button>
</li>
methods:
{
markComplete(task)
{
return task.status = true;
},
RTFM:
You can use the v-repeat directive to repeat a template element
based on an Array of objects on the ViewModel. For every object in the
Array, the directive will create a child Vue instance using that
object as its $data object. These child instances inherit all data
on the parent, so in the repeated element you have access to
properties on both the repeated instance and the parent instance. In
addition, you get access to the $index property, which will be the
corresponding Array index of the rendered instance.
var demo = new Vue({
el: '#demo',
data: {
parentMsg: 'Hello',
items: [
{ childMsg: 'Foo' },
{ childMsg: 'Bar' }
]
}
})
<script src="https://unpkg.com/vue#0.12.16/dist/vue.min.js"></script>
<ul id="demo">
<li v-repeat="items" class="item-{{$index}}">
{{$index}} - {{parentMsg}} {{childMsg}}
</li>
</ul>
Source:
https://012.vuejs.org/guide/list.html
Note: The directive v-repeat is available in old versions of Vue.js :-)
Well I hope to explain, I'm generating this data from a component, when I click the checkbox changes in the generated data are not reflected, but when clicking the button with a data already in the instance changes are made, I appreciate if you explain Why or do they have a solution?
this my code
js
Vue.component('fighters', {
template: '#fighters-template',
data() {
return {
items: [
{ name: 'Ryu' },
{ name: 'Ken' },
{ name: 'Akuma' }
],
msg: 'hi'
}
},
methods: {
newData() {
this.items.forEach(item => {
item.id = Math.random().toString(36).substr(2, 9);
item.game = 'Street Figther';
item.show = false;
});
this.items.push()
},
greeting() {
this.msg = 'hola'
}
}
});
new Vue({
el: '#app'
})
html
<main id="app">
<fighters></fighters>
</main>
<template id="fighters-template">
<div class="o-container--sm u-my1">
<ul>
<li v-for="item in items">
<input type="checkbox" v-model="item.show">
{{ item.name }}</li>
</ul>
<button class="c-button c-button--primary" #click="newData()">New Data</button>
<h2>{{ msg }}</h2>
<button class="c-button c-button--primary" #click="greeting()">Greeting</button>
<hr>
<pre>{{ items }}</pre>
</div>
</template>
this live code
https://jsfiddle.net/cqx12a00/1/
Thanks for you help
You don't declare the show variables that your checkboxes are bound to, so they are not reactive – Vue is not aware when one is updated.
It should be initialized like so:
items: [
{ name: 'Ryu', show: false },
{ name: 'Ken', show: false },
{ name: 'Akuma', show: false }
]
You might think that newData would fix it, since it assigns a show member to each item, but Vue cannot detect added properties so they're still not reactive. If you initialized the data as I show above, then the assignment would be reactive.
If you want to add a new reactive property to an object, you should use Vue.set.
I have a Todo class that has a delete method. I would like to use the delete method as an #click handler:
<div v-for="todo in todos">
<v-btn #click="todo.delete">Delete</v-btn>
</div>
Unfortunately this gives me:
Invalid handler for event "click": got undefined
Here's a simple codepen example that shows the core concept working: https://codepen.io/nickforddesign/pen/YYwgKx
The issue is that the items in your todos array don't have the method.
<div class="app">
<ul>
<li v-for="todo in todos">
{{ todo }}
<button #click="todo.delete">Delete</button>
</li>
</ul>
</div>
And the js
new Vue({
el: '.app',
data() {
return {
todos: [{
name: '1',
delete() {
alert(`delete`)
}
},{
name: '2',
delete() {
alert(`delete`)
}
}]
}
}
})
I am using vue.js 2.0,This demo below is working.
<div class="container" id="app">
<ol>
<li v-for="(todo,index) in todos">
{{ index }} {{ todo.text }}
</li>
</ol>
</div>
<script>
new Vue({
el: '#app',
data: {
todos: [
{ text: 'Learn JavaScript' },
{ text: 'Learn Vue' },
{ text: 'Build something awesome' }
]
}
});
</script>
I use axios(https://github.com/mzabriskie/axios) to send ajax requests and get the data from backend,I can see the data in console,but the data can not be shown in view.
<div class="container" id="app">
<ol>
<li v-for="(todo,index) in todos">
{{ index }} {{ todo.text }}
</li>
</ol>
</div>
<script>
new Vue({
el: '#app',
data: {
todos: []
},
mounted: function () {
this.$nextTick(function () {
axios.get('/articles')
.then(function (response) {
console.log(response);
this.todos = response.data;
})
.catch(function (error) {
console.log(error);
});
});
}
});
</script>
And, the simulation below is working.
<div class="container" id="app">
<ol>
<li v-for="(todo,index) in todos">
{{ index }} {{ todo.text }}
</li>
</ol>
</div>
<script>
new Vue({
el: '#app',
data: {
todos: []
},
mounted: function () {
this.$nextTick(function () {
var arr=[
{ text: 'Learn JavaScript' },
{ text: 'Learn Vue' },
{ text: 'Build something awesome' }
];
this.todos = arr;
});
}
});
</script>
I think, you need preserve "this" before axios.get (self=this) and then change
this.todos = response.data;
to
self.todos = response.data;