Reputation: 3404
I'm playing with vue.js for learning purposes consisting of different components, one of them being a classic to do list. For now, everything is within one component.
I want to change the text of a button after it is clicked to hide an element from "hide" to "show" - I'm going about this by setting a text data object and then changing it in a function.
See below:
<div id="app">
<ul>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ul>
<input type="text" id="list-input">
<input type="submit" id="list-submit" v-on:click="addItem">
<span id="error" style="color: red; display: none;">Please Enter Text</span>
<ul>
<todoitem></todoitem>
<todoitem></todoitem>
<todoitem></todoitem>
</ul>
<h2 v-if="seen">SEEN</h2>
<button id="hide-seen" v-on:click="toggleSeen">{{ button.text }}</button>
</div>
<script type="text/javascript">
// components
Vue.component('todoitem', {
template: "<li>Test Item</li>"
})
// app code
var app = new Vue({
el: '#app',
data: {
todos: [
{ text: 'Sample Item 1' },
{ text: 'Sample Item 2' },
{ text: 'Sample Item 3' }
],
button: [
{ text: 'Hide'}
],
seen: true
},
methods: {
addItem: function() {
let item = document.getElementById("list-input").value;
let error = document.getElementById("error");
if (item == "") {
error.style.display = "block";
} else {
app.todos.push({ text: item });
error.style.display = "none";
}
},
toggleSeen: function() {
app.seen = false
app.button.push({ text: 'Show' });
}
}
})
</script>
Unexpectedly, the button is blank on both hide and show states. Being new to vue, this seems like a strange way to go about doing it. Is changing data in this context bad practice? I don't understand how to fix this, as I have no errors in my console.
Upvotes: 17
Views: 75365
Reputation: 11445
You can achieve this by using refs in vuejs:
<body>
<div id = 'app'>
<button @click="changeState" ref="btnToggle">Hide</button>
<div v-show="show">
<h1>1 to 100</h1>
<p v-for="i in 100">{{i}}</p>
</div>
</div>
<script>
const app = new Vue({
el:'#app',
data: function(){
return{
show: true
}
},
methods: {
changeState: function(){
this.show = !this.show;
this.$refs.btnToggle.innerText = this.show?'Hide':'Show';
}
},
});
</script>
</body>
Upvotes: 6
Reputation: 2521
Here you have your code in a snipplet.
I change your button by a plain object instead of an array and small adaptation in method toggleSeen.
// components
Vue.component('todoitem', {
template: "<li>Test Item</li>"
})
// app code
var app = new Vue({
el: '#app',
data: {
todos: [
{ text: 'Sample Item 1' },
{ text: 'Sample Item 2' },
{ text: 'Sample Item 3' }
],
button: {
text: 'Hide'
},
seen: true
},
methods: {
addItem: function() {
let item = document.getElementById("list-input").value;
let error = document.getElementById("error");
if (item == "") {
error.style.display = "block";
} else {
app.todos.push({ text: item });
error.style.display = "none";
}
},
toggleSeen: function() {
app.seen = !app.seen;
app.button.text = app.seen ? 'Hide' : 'Show';
}
}
});
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="app">
<ul>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ul>
<input type="text" id="list-input">
<input type="submit" id="list-submit" v-on:click="addItem">
<span id="error" style="color: red; display: none;">Please Enter Text</span>
<ul>
<todoitem></todoitem>
<todoitem></todoitem>
<todoitem></todoitem>
</ul>
<h2 v-if="seen">SEEN</h2>
<button id="hide-seen" v-on:click="toggleSeen">{{ button.text }}</button>
</div>
Upvotes: 13