I am have an array of items that will be fetched fom an API. First, I display the string replacing ### with ______. Then when I click the buttons I want to replace them with <span>word</span>. so I'am using using v-html. I thought the new element would be shown but it doesn't. what would I have to do?
Code: https://jsfiddle.net/uosm30p9/
var example1 = new Vue({
el: '#example',
data: {
items: [{
str: 'This is ###.',
list: ['Frank', 'Eva']
},
{
str: 'I am not ###.',
list: ['George', 'John', 'Mark']
}
],
},
computed: {},
methods: {
createStr(item) {
item.newStr = item.str;
item.newStr = item.newStr.replace("###", "________")
return item.newStr
},
update(item, word) {
item.newStr = item.str;
var span = "<span class='.span1'>" + word + "</span>";
item.newStr = item.newStr.replace("###", span)
console.log(item.newStr);
}
}
});
.span1 {
color: blueviolet;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="example">
<ul>
<li v-for="(item,i) in items">
<span v-html="createStr(item)"></span>
<ul>
<li v-for="(word,j) in item.list">
<button v-on:click="update(item,word)">{{word}}</button>
</ul>
</li>
</ul>
</div>
Ok, in order to solve your problem more easily and separating concerns, I came to a solution by setting up a template and storing the current value in each element "state".
HTML:
<div id="example">
<ul>
<li v-for="(item,i) in items">
<span v-html="createStr(item)"></span>
<ul>
<li v-for="(word,j) in item.list">
<button v-on:click="update(item, j)">{{word}}</button>
</ul>
</li>
</ul>
</div>
Javascript:
var example1 = new Vue({
el: '#example',
data: {
defaultReplacement: "_________",
items: [{
selectedOption: null,
template: 'This is <b class="span1">###</b>.',
list: ['Frank', 'Eva']
},
{
selectedOption: null,
template: 'I am not <b class="span2">###</b>.',
list: ['George', 'John', 'Mark']
}
],
},
computed: {},
methods: {
createStr(item) {
var listItem = (item.selectedOption != null) ? item.list[item.selectedOption] : this.defaultReplacement;
return item.template.replace("###", listItem);
},
update(item, j) {
item.selectedOption = j;
}
}
});
Here's the working example: https://jsfiddle.net/feload/rhnf8zv4/5/
var example1 = new Vue({
el: '#example',
data: {
items: [{
str: 'This is ###.',
list: ['Frank', 'Eva'],
current: "________"
},
{
str: 'I am not ###.',
list: ['George', 'John', 'Mark'],
current: "________",
}
],
},
computed: {},
methods: {
createStr(item) {
item.newStr = item.str;
item.newStr = item.newStr.replace("###", item.current);
return item.newStr;
},
update(item, word, idx) {
item.current = word;
this.$set(this.items, idx, item);
}
}
});
.span1 {
color: blueviolet;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="example">
<ul>
<li v-for="(item,i) in items">
<span v-html="createStr(item)"></span>
<ul>
<li v-for="(word,j) in item.list">
<button v-on:click="update(item,word, i)">{{word}}</button>
</ul>
</li>
</ul>
</div>
First try making your data object reactive so that alterations to the item array can be observed by Vue:
data: function () {
return {
items: [
{
str: 'This is ###.',
list: ['Frank', 'Eva']
},
{
str: 'I am not ###.',
list: ['George', 'John', 'Mark']
}
]
}
},
Look at the example at the bottom of this page:
https://v2.vuejs.org/v2/guide/reactivity.html
Related
Please can someone teach me the method to swap two different data on click
For example, we have a data
data() {
return {
data_one: [
{
name: "Simo",
age: "32"
}
],
data_two: [
{
name: "Lisa",
age: "25"
}
],
}
},
then I want to put this data on v-for, and I want to add two buttons to swap from data_one and data_two and display data_one as default.
<button #click="change_to_data_one">Data 1<button>
<button #click="change_to_data_two">Data 2<button>
<li v-for="item in data_one">{{item.name}} - {{item.age}}<li>
🙏🙏🙏🙏🙏
Try to use computed property:
new Vue({
el: "#demo",
data() {
return {
data_one: [{name: "Simo", age: "32"}],
data_two: [{name: "Lisa", age: "25"}],
selected: "data_one"
}
},
computed: {
showData(){
return this[this.selected]
}
},
methods: {
swap(val) {
this.selected = val
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<button #click="swap('data_one')">Data 1</button>
<button #click="swap('data_two')">Data 2</button>
<ul>
<li v-for="(item, i) in showData" :key="i">{{item.name}} - {{item.age}}</li>
</ul>
</div>
I'm Building a tree-like structure in vue. I tried to do this with the data function but in that case, all the elements in the same level of the tree getting these classes although I just want clicked element to achieve this I tried this with the ref but don't know how to achieve that parent element selector part with it as I'm new to Vue till now i don't know how to tackle this .
this.parentElement.querySelector(".nested").classList.toggle("active");
this.classList.toggle("caret-down");
Please take a look at one of solutions (if I understood you correctly) in following snippet
new Vue({
el: '#demo',
data() {
return {
tree: [
{parent: 'AAA', childs: []},
{parent: 'BBB', childs: [{child: 'bbb'}, {child: 'ccc'}]},
{parent: 'CCC', childs: [{child: 'ddd'}, {child: 'eee'}, {child: 'fff'}]},
{parent: 'DDD', childs: []}
],
selected: null,
active: null
}
},
methods: {
select(item, idx) {
if (this.tree[idx].childs.length) {
this.selected = idx
this.active = null
} else {
this.active = item.parent + idx
this.selected = null
}
},
activate(itm, i) {
this.active = itm.child + i
}
}
})
li {
cursor: pointer;
}
.active {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<ul>
<li v-for="(item, idx) in tree" :key="idx">
<p #click="select(item, idx)" :class="active === item.parent + idx ? 'active' : ''">{{ item.parent }}</p>
<ul v-if="selected === idx">
<li v-for="(itm, i) in item.childs" :key="i">
<p #click="activate(itm, i)" :class="active === itm.child + i ? 'active' : ''">{{ itm.child }}</p>
</li>
</ul>
</li>
</ul>
</div>
I want that in my v-for, when I click the UP button, the li which is linked to the button increases his State by +1.
Here is a bit of my code:
Vue.component('app', {
data: function () {
return {
messages: '',
state: 0,
id: 0,
todo: [],
columns: ["todo", "doing", "done"],
}
},
methods: {
upElement: function (id) {
this.id
this.state++;
},
removeElement: function (key) {
this.todo.splice(key, 1);
},
},
template: `
<ul>
<li v-if="state === 0" v-for="(item, key) in todo" v-bind:messages="todo.messages + todo.state + todo.id" :key="item.id" v-bind:id="key">
<span>{{item.messages}}</span></br>
<button v-on:click="upElement">UeP</button>
<button v-on:click="removeElement(key)">remove</button>
</li>
</ul>=
`,
})
I wanted to put an id to target the li but it does not work
You can pass the item object directly to your upElement function and modify the state property.
Vue.component('app', {
data: function () {
return {
messages: '',
state: 0,
id: 0,
todo: [],
columns: ["todo", "doing", "done"],
}
},
methods: {
upElement: function (item) {
item.state++;
},
removeElement: function (key) {
this.todo.splice(key, 1);
},
},
template: `
<ul>
<li v-if="state === 0" v-for="(item, key) in todo" v-bind:messages="todo.messages + todo.state + todo.id" :key="item.id" v-bind:id="key">
<span>{{item.messages}}</span></br>
<button v-on:click="upElement(item)">UeP</button>
<button v-on:click="removeElement(key)">remove</button>
</li>
</ul>=
`,
})
How can we highlight a item in a list of item when the particular item is clicked? Should we use id as reference?
<li v-for="todo in todos">
<label>
<a href="#"
v-on:click="toggle(todo)"
:style="{color:activeColor}"
>
{{ todo.text }}
</a>
</label>
</li>
toggle: function(todo){
this.activeColor = 'red'
}
I tried here:
https://jsfiddle.net/eywraw8t/110976/
You can add activeIndex to store current active index:
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="(todo, idx) in todos">
<label>
<a href="#"
v-on:click="toggle(idx)"
v-bind:checked="todo.done"
:class="{'active': idx == activeIndex}"
>
{{ todo.text }}
</a>
</label>
</li>
</ol>
</div>
new Vue({
el: "#app",
data: {
activeColor:String,
todos: [
{ text: "Learn JavaScript", done: false },
{ text: "Learn Vue", done: false },
{ text: "Play around in JSFiddle", done: false },
{ text: "Build something awesome", done: false }
],
activeIndex: null
},
methods: {
toggle: function(index){
this.activeIndex = index
}
}
and in css
.active {
color: red;
}
Demo: https://jsfiddle.net/Lv7eanru/
This is another solution to highlight selected item in a list using VueJS :
<div id="app">
<ul>
<li v-for="value in objectArray" v-on:click="highlight($event)" >
First name : {{ value.firstName }} -- Last name : {{ value.lastName }}
</li>
</ul>
and in JS file we have:
Vue.createApp({
data() {
return {
objectArray: [{
firstName: 'John',
lastName: 'Doe'
},
{
firstName: 'Amily',
lastName: 'Brown'
},
{
firstName: 'Jack',
lastName: 'London'
},
],
}
},
methods: {
highlight: function (event) {
for (var i = 0; i < event.target.parentElement.children.length; i++) {
event.target.parentElement.children[i].classList.remove('bg-warning');
}
event.target.classList.add('bg-warning');
}
},
}).mount('#app');
I'm getting my example from Vue JS docs
If I have a v-for that's filtered, how do I get the real index of this user in my array? Not the index of the current iteration, but the index of the item from the array.
<div id="filter-by-example">
<ul>
<li v-for="user in users | filterBy 'Jim' in 'name'">
{{ user.name }}
{{ $index }} <!--I want Jim's index to be 3, not 0-->
</li>
</ul>
</div>
Vue JS:
new Vue({
el: '#filter-by-example',
data: {
users: [
{ name: 'Bruce' },
{ name: 'Chuck' },
{ name: 'Jackie' },
{ name: 'Jim' },
]
}
})
This should do it:
new Vue({
el: '#filter-by-example',
data: {
users: [
{ name: 'Bruce' },
{ name: 'Chuck' },
{ name: 'Jackie' },
{ name: 'Jim' },
]
},
methods : {
getIndexOfItem: function(arr, item) {
return arr.indexOf(item);
}
}
});
<script src="https://unpkg.com/vue#next/dist/vue.js"></script>
<div id="filter-by-example">
<ul>
<li v-for="user in users">
{{getIndexOfItem(users, user)}} - {{user.name}}
</li>
</ul>
</div>
Added a getIndexOfItem method into the methods collection and in the v-for passed in the array and item then returned the item index, this seems complex but most other implementations didn't seem to work work.
Edit 2
I removed the function inside the methods collection.
<li v-for="(user, index) in users | filterBy 'Jim' in 'name'">
https://jsbin.com/misagagewo/edit?output
As far as I know you can't. You can do something like this though.
<div id="filter-by-example">
<ul>
<li v-for="user in users | filterBy 'Jim' in 'name'">
{{ user.name }}
{{ user._index }}
</li>
</ul>
</div>
JS:
function fixupObjArray(arr) {
arr.forEach((e,i) => e._index = i);
return arr;
}
new Vue({
el: '#filter-by-example',
data: {
users: fixupObjArray( [
{ name: 'Bruce' },
{ name: 'Chuck' },
{ name: 'Jackie' },
{ name: 'Jim' },
] )
}
})