I have a layout on which i am looping to get text fields and a button. How do i add a function on the button so that it clears only it's respective fields.
Check out the fiddle here.
<div id="app">
<h2>Each text with it's own state and clear should clear the respective
text fields</h2>
<ul v-for="todo in todos">
<li>
<input type="text" :placeholder="`${todo.text}`">
</li>
<li>
<input type="text" :placeholder="`${todo.text1}`">
</li>
<button>Clear</button>
</ul>
new Vue({
el: "#app",
data: {
todos: [
{ text: "Learn JavaScript", text1:"Hey" },
{ text: "Learn Vue", text1:"Hello" },
{ text: "Play around in JSFiddle", text1:"Ciao" },
{ text: "Build something awesome", text1:"Something"}
]
}
})
If you want to clear a specific fields you could add a method clear which takes the index as parameter but before that you should add value and value1 items to each todo and bind them to fields as follows:
new Vue({
el: "#app",
data: {
todos: [{
text: "Learn JavaScript",
text1: "Hey",
value1:'',
value:''
},
{
text: "Learn Vue",
text1: "Hello",
value1:'',
value:''
},
{
text: "Play around in JSFiddle",
text1: "Ciao",
value1:'',
value:''
},
{
text: "Build something awesome",
text1: "Something",
value1:'',
value:''
}
]
},
methods:{
clear(i){
this.todos[i].value='';
this.todos[i].value1='';
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<h2>Each text with it's own state and clear should clear the respective text fields</h2>
<ul v-for="(todo,i) in todos">
<li>
<input type="text" :placeholder="`${todo.text}`" v-model="todo.value">
</li>
<li>
<input type="text" :placeholder="`${todo.text1}`" v-model="todo.value1">
</li>
<button #click="clear(i)">Clear</button>
</ul>
</div>
You really should go through the docs at https://v2.vuejs.org/v2/
You are missing many of the basic constructors to achieve your objective. First, you will need to add the click event to your button. (https://v2.vuejs.org/v2/guide/events.html)
Next, you will need to reference the index of the todos during rendering (https://v2.vuejs.org/v2/guide/list.html)
From here you can create a simple method called clear:
new Vue({
el: "#app",
data: {
todos: [
{ text: "Learn JavaScript", text1:"Hey" },
{ text: "Learn Vue", text1:"Hello" },
{ text: "Play around in JSFiddle", text1:"Ciao" },
{ text: "Build something awesome", text1:"Something"}
]
},
methods: {
clear (index) {
// Allows for unlimited keys
for (let key in this.todos[index]) {
this.$set(this.todos[index], key, null);
}
}
}
})
Notice that in the clear method I am ensuring reactivity by using the $set method (https://v2.vuejs.org/v2/api/#vm-set) and referencing the index that was passed.
Lastly, I bound the inputs value to the todo model using Vue's v-model, do I get extra credit? (https://v2.vuejs.org/v2/api/#v-model)
Completed code:
https://jsfiddle.net/cdsgu62L/10/
Related
I have an odd task. I am simply trying to add an additonal function on an element when its clicked. I cant seem to trigger the addScroll function that is found within my methods. As you can see, the div should be appended to the screen when the button is clicked. Once that div is clicked as well, the remove method is applied and I also want to apply the addScrollBack().
new Vue({
el: "#app",
data: {
chocs: [
{ text: "Learn JavaScript", done: false },
{ text: "Learn Vue", done: false },
{ text: "Play around in JSFiddle", done: true },
{ text: "Build something awesome", done: true }
]
},
methods: {
addScrollBack: function(){
alert("test");
},
handlePosterClick: function(choc){
alert("ckciked")
window.top.$(".2l-body").css("overflow","hidden");
$("#cook").append(`<div style="background-color:blue;height:200px; width:300px" onclick="document.querySelector('#popover-div').remove();addScrollBack();>test</div>`);
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="cook">
</div>
<button v-on:click="handlePosterClick(choc)">
Book
</button>
</div>
Look at this :
https://codepen.io/hl037/pen/QWOjwyK
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
{{displayDiv}}
<div id="cook">
<div
v-if="displayDiv"
style="background-color:blue;height:200px; width:300px"
v-on:click="onDivClicked"
>
test
</div>
</div>
<button v-on:click="displayDiv=true">
Book
</button>
</div>
new Vue({
el: "#app",
data: {
displayDiv:false,
chocs: [
{ text: "Learn JavaScript", done: false },
{ text: "Learn Vue", done: false },
{ text: "Play around in JSFiddle", done: true },
{ text: "Build something awesome", done: true },
],
},
methods: {
onDivClicked(){
/*document.querySelector('#popoverdiv').remove();*/
this.addScrollBack();
},
addScrollBack: function(){
alert("test");
},
handlePosterClick: function(choc){
},
}
})
...Instead of manipulating the dom yourself, just use vue's template, with a model controlling its behavior. The same applies to your other component (the popup) : it should instead listen on a custom event on this component to add/remove scroll using reactivity.
Using vanilla javascript for dom modification, event-handling etc. is NOT recommended with vue. Always use vue's way of doing it. vanilla dom modification should only be done by experts, mostly to interface with non-vue code.
Not clear, but suggestion is use v-html instead of append
new Vue({
el: "#app",
data: {
cook: "Old content OR blank",
chocs: [
{ text: "Learn JavaScript", done: false },
{ text: "Learn Vue", done: false },
{ text: "Play around in JSFiddle", done: true },
{ text: "Build something awesome", done: true }
]
},
methods: {
addScrollBack: function(){
alert("test");
},
handlePosterClick: function(choc){
//alert("ckciked " + choc)
// window.top.$(".2l-body").css("overflow","hidden");
// inline Scripting not recommanded,
this.cook= `<div style="background-color:blue;height:200px; width:300px" >test</div>`;
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="cook" v-html="cook">
</div>
<button v-on:click="handlePosterClick('choc')">
Book
</button>
</div>
Well, it's not easy to explain.
I have a list of checkboxes generated from reactive data. When you check one of the checkboxes, one of the entries of the reactive data is deleted.
The list is then updated.
The next checkbox is then placed under the mouse cursor and is "activated" by releasing the mouse button. This behavior is unwanted, can you see a way to avoid this?
Here is the code to illustrate this case:
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="todo in todos">
<label>
<input type="checkbox"
v-on:change="toggle">
{{ todo.text }}
</label>
</li>
</ol>
</div>
Script part:
new Vue({
el: "#app",
data: {
todos: [
{ text: "Learn JavaScript" },
{ text: "Learn Vue" },
{ text: "Play around in JSFiddle" },
{ text: "Build something awesome" }
]
},
methods: {
toggle: function(){
this.todos.splice(1,1)
}
}
})
Also a live test: https://jsfiddle.net/m10jyLut/7/
I don't know if my design is correct. I would like to avoid a too hackneyed solution.
Thank you very much for your guess.
I added "key" to v-for, which is always a good idea, and passing todo.id with toggle().
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="todo in todos" :key="todo.id">
<label>
<input type="checkbox"
v-on:change="toggle(todo.id)">
{{ todo.text }}
</label>
</li>
</ol>
</div>
Your script tag should be like this:
new Vue({
el: "#app",
data: {
todos: [
{ id: Math.random() * 100000, text: "Learn JavaScript", },
{ id: Math.random() * 100000, text: "Learn Vue", },
{ id: Math.random() * 100000, text: "Play around in JSFiddle", },
{ id: Math.random() * 100000, text: "Build something awesome", }
]
},
methods: {
toggle(id) {
this.todos = this.todos.filter(todo => todo.id !== id)
}
}
})
In Vue.js, it's always a good idea to add key to v-for, and working with ids for rendering operations.
In my case, I have data array with multiple objects
data() {
return {
selected: 0,
presetData: [true, true, true],
data: [
{
name: "name 1"
},
{
name: "name 2"
}
]
};
},
then I want to push inside each object in data like below
setNewData() {
this.data.forEach((o, i) => {
this.$set(this.data[i], "time", this.presetData);
});
},
now my with presetData pushed into data will look like this
data: [
{
name: "name 1",
time: [true, true, true]
},
{
name: "name 2",
time: [true, true, true]
}
]
and I want to change individual time property of each object, which I use something like below
$set(item.time,selected,true)
My Issue
my issue is, this going to change both objects time property. How do I first push/set correctly presetData to data, below is my entire code , I'm sorry I'm very new to programming, here is the link to jsfiddle
new Vue({
el: "#app",
data() {
return {
selected: 0,
presetData: [true, true, true],
data: [
{
name: "name 1",
},
{
name: "name 2",
}
]
};
},
methods: {
setNewData() {
this.data.forEach((o, i) => {
this.$set(this.data[i], "time", this.presetData);
});
},
}
})
<div id="app">
<button #click="setNewData">Set Data</button>
<br>
<br>
<select v-model="selected">
<option>0</option>
<option>1</option>
<option>2</option>
</select>
<div v-for="item in data" :key="item.id">
<p>{{item.name}}</p>
<p>{{item.time}}</p>
<button #click="$set(item.time,selected,true)">Change True</button>
<button #click="$set(item.time,selected,false)">Change False</button>
</div>
This is an object reference issue. Each of your time properties references the same array (presetData). You can break out of this problem by making shallow copies via spread syntax.
You can also avoid Vue.set() when assigning new data using the same technique
setNewData() {
this.data = this.data.map(d => ({
...d, // create a shallow copy of each data item
time: [...this.presetData] // add "time" as a shallow copy of presetData
}))
},
To change individual array elements within the time property, you need to continue using Vue.set(), ie
this.$set(item.time, selected, true)
In my case, I have data array with multiple objects
data() {
return {
selected: 0,
presetData: [true, true, true],
data: [
{
name: "name 1"
},
{
name: "name 2"
}
]
};
},
then I want to push inside each object in data like below
setNewData() {
this.data.forEach((o, i) => {
this.$set(this.data[i], "time", this.presetData);
});
},
now my with presetData pushed into data will look like this
data: [
{
name: "name 1",
time: [true, true, true]
},
{
name: "name 2",
time: [true, true, true]
}
]
and I want to change individual time property of each object, which I use something like below
$set(item.time,selected,true)
My Issue
my issue is, this going to change both objects time property. How do I first push/set correctly presetData to data, below is my entire code , I'm sorry I'm very new to programming, here is the link to jsfiddle
new Vue({
el: "#app",
data() {
return {
selected: 0,
presetData: [true, true, true],
data: [
{
name: "name 1",
},
{
name: "name 2",
}
]
};
},
methods: {
setNewData() {
this.data.forEach((o, i) => {
this.$set(this.data[i], "time", this.presetData);
});
},
}
})
<div id="app">
<button #click="setNewData">Set Data</button>
<br>
<br>
<select v-model="selected">
<option>0</option>
<option>1</option>
<option>2</option>
</select>
<div v-for="item in data" :key="item.id">
<p>{{item.name}}</p>
<p>{{item.time}}</p>
<button #click="$set(item.time,selected,true)">Change True</button>
<button #click="$set(item.time,selected,false)">Change False</button>
</div>
This is an object reference issue. Each of your time properties references the same array (presetData). You can break out of this problem by making shallow copies via spread syntax.
You can also avoid Vue.set() when assigning new data using the same technique
setNewData() {
this.data = this.data.map(d => ({
...d, // create a shallow copy of each data item
time: [...this.presetData] // add "time" as a shallow copy of presetData
}))
},
To change individual array elements within the time property, you need to continue using Vue.set(), ie
this.$set(item.time, selected, true)
I am working on a basic tree view that will list a few items, and I want to be able to alter the text of the child item based upon a user input.
view:
<div class="treeviewUI">
<p>
Test Tree View Model
</p>
<p><strong>Enter Child One: <input data-bind="value: $parent.childOne"/></strong> <!-- also tried just childOne -->
</p>
<ul id='treeMenu' data-bind="foreach: menu">
<li>
<div data-bind="click: function() {$parent.toggle($data)}">
<span data-bind="text: $data.text></span>
<ul data-bind="visible: $data.expanded,
foreach: {data: $data.children, as 'child' }">
<li data-bind="text:child.text"/>
</ul>
</div>
</li>
</ul>
and the viewmodel:
define([knockout'], function (ko) {
var childOne = ko.observable();
var viewModel = {
menu: [
text: "Item 1",
children: [
{ text: childOne() },
{ text: "child 1b" }
],
expanded: ko.observable(false)
},
{
text: "Item 2",
children: [
{ text: "child 2a" },
{ text: "child 2b" }
],
expanded: ko.observable(false)
}
],
toggle: function(node) {
node.expanded(!node.expanded());
}
};
return viewModel;
});
However, entering input for the childOne does not update the treeView subitems. Am I missing a binding or just using the wrong type of binding. Or is there something more complicated going on here?
JSFIDDLE LINK: http://jsfiddle.net/xQ7GS/54/
When writing text: childOne() you are asigning the value of the childOne observable and not the function itself.
So your text will contain undefined and not the ko.observable, you can fix this with removing the ():
children: [
{ text: childOne },
{ text: "child 1b" }
],
Demo JSFiddle.