vuejs repeat static html on #click - vue.js

I'm not sure if this is possible in VUEJS.
I want to repeat an element a specific number of times (by passing a number on the #click of a button). Please see below sample code:
<button #click="function"> where it will tell how many time to repeat
<li v-for="item in (value from btn click)">test</li>
when I add code like
<li v-for="item in 4">
it works but I need this repeat (4) on click of button.

v-for with a range
v-for can also take an integer. In this case it will repeat the
template that many times.
<span v-for="n in 10">{{ n }} </span>
You can use a data item instead of a constant.
new Vue({
el: '#app',
data: {
n: 4
}
});
<script src="//unpkg.com/vue#latest/dist/vue.js"></script>
<div id="app">
<span v-for="i in n">{{i}}</span>
</div>

You can pass a number from your button, catch it in a method, and add it to the number you're using to loop. If you want the loop to be one element longer each click, you can pass it 1.
<button #click="addToLoop(1)">
See example: https://jsfiddle.net/56rnv91j/

From documentation: "v-for can also take an integer. In this case it will repeat the template that many times." link

Related

How to refer to specific dynamically added component from number of dynamically added components in Vue, version 2.9

What or where is individual id or any other element that I can call to run a function on component.
Example: using add button I'm dynamically creating colored squares. Each square has close button.
Then I want to delete one of squares, let's say the blue one (third child of template).
v-bind:id='var' doesn't works because then all squares have the same id.
You can use ref, you can define ref in every added component. The ref is array. you can refrence component through index of the ref.
for example;<div v-for="(item) in arr" :key="item.id"> <span ref="testRef"> item.name </span> </div>, you can use 'this.$refs.testRef[index]' find component which you want.
There are multiple options. For instance, in your v-for loop you can get the index this way: (official docs)
<div v-for="(item, index) in myList" :key="index">
{{ item.name }}
</div>
You could then for example use the index in a ref to access the element for the script.
Another option is to pass the event instance to the onclick listener with the special keyword $event, and use this to get the element:
<div ... #click="myFunction($event)">
{{ item.name }}
</div>
And then in your script
myFunction(ev) {
// do something with the element that was clicked on
console.log(ev.target)
}
However, a more 'vue' way would be to not mess with the elements, but only manipulate the underlying data and let vue worry about representing the data with elements on your page. For instance, you could make your squares be represented by a list of objects, containing their own data own the state (opened or closed). So in your script you have:
data() {
return {
squares: [
{ color: "ff0000", opened: true },
...
]
}
},
And in your template something like
<div
v-for="square in squares"
v-show="suare.opened"
#click="square.opened = false"
> ...

How to know the iteration in v-for

i'm in Vue.js
I made a radio input component, I use a v-for to display all the input and label, I would like to know if I can tell it to pass the checked attribute to the element from the first iteration of the v-for loop
<div v-for="(option) in options" :key="option.name">
<label class="form-check-label mr-2" :for="option.for">
{{ option.name }}
</label>
<input
v-model="selectedChoice"
class="mr-4"
type="radio"
name="radio"
:id="option.for"
/>
</div>
Thanks for your help
if I understand you correct you want to check your first radio button from your v-for.
You have two options to achieve that:
First option
You can set selectedChoice to your first choice like this:
data() {
return {
options: ['yourChoice1', 'yourChoice2'] //you have to set your array in here
selectedChoice: 'yourChoice1',
}
}
Second option
You set your data prop to the first item in your array - this is able because you're using v-model - you do it like this:
this.selectedChoice = this.yourChoice[0]
Hopefully this helps you out - please let me know!

How to append a static components to a dynamic ones in Vue?

What I'm trying to achieve is this: I have a <v-window> parent component that takes <v-window-item> children. The first child loops thru a Vuex getter that returns an object and depending on its content dynamically visualizes cards. However, I have another static component that is like a summary and contains a logout button that I want to append to the last dynamic <v-window> generated from the store. Here's how I've set up my code so far:
<v-window v-model="reportPage">
<v-window-item v-for="card in getSelectedCard" :key="card.id">
</v-window-item>
</v-window>
Can someone give me some pointers on how to achieve that? Thanks in advance!
I think there are a few ways to achieve such a thing, the one I would use is conditional rendering based on the current index:
new Vue({
el: "#app",
data: {
someList: [ "first", "middle", "last" ]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ol>
<li v-for="(item, index) in someList">
{{ item }}
<span v-if="index === someList.length - 1">
- logout button component here
</span>
</li>
</ol>
</div>
Of course the content of my v-if could be a prop of your v-window-item:
<v-window-item v-for="(card, index) in getSelectedCard" :key="card.id" show-logout-button="index === getSelectedCard.length - 1">
Or if you have a slot in your v-window-item:
<v-window-item v-for="(card, index) in getSelectedCard" :key="card.id">
<logout-button v-if="index === getSelectedCard.length - 1" />
</v-window-item>
There are slots that can help you. You simply need to add a <slot></slot> to your child component, then you'll be able to put whatever you like inside your child tag !

passing an input value directly into a function within a loop

So basically I have this;
<ul class="queryView">
<li
v-for="(object, index) in Objects"
>
{{ object.key }}
<input
type="text"
#input="saveValue(value)"
>
</li>
</ul>
...
saveValue(value){
... do somthing with value
},
Since it's in a loop, v-model does not work as they will affect each looped element. i.e If in one input field I put in a word all of the fields will display the same word.
thus I need to get the input value directly into the function.
v-model does work if properly used.
See this JS Fiddle:
https://jsfiddle.net/eywraw8t/167740/
But if you want to use a function to handle the values, it is also fine, but much more verbose.
See this JS Fiddle:
https://jsfiddle.net/eywraw8t/167731/
See the docs: https://v2.vuejs.org/v2/api/#v-on
[…] the method receives the native event as the only argument. If using inline statement, the statement has access to the special $event property: v-on:click="handle('ok', $event)".
The "input" event has a target property, which in your case is your <input> element, on which you can read its current value.
new Vue({
el: '#app',
methods: {
saveValue(event) {
const target = event.target;
const value = target.value;
console.log(value);
},
otherMethod(text1, event) {
console.log(text1);
console.log(event.target.value);
},
},
});
<script src="https://unpkg.com/vue#2"></script>
<div id="app">
<ul>
<li v-for="i in 3">
{{i}}<input #input="saveValue" />
</li>
</ul>
<p>
With inline statement:
<input #input="otherMethod('other', $event)" />
</p>
</div>

How to avoid vue component redraw?

I have prepared tag input control in Vue with tag grouping. Templates includes:
<script type="text/x-template" id="tem_vtags">
<div class="v-tags">
<ul>
<li v-for="(item, index) in model.items" :key="index" :data-group="getGroupName(item)"><div :data-value="item"><span v-if="typeof model.tagRenderer != 'function'">{{ item }}</span><span v-if="typeof model.tagRenderer == 'function'" v-html="tagRender(item)"></span></div><div data-remove="" #click="remove(index)">x</div></li>
</ul>
<textarea v-model="input" placeholder="type value and hit enter" #keydown="inputKeydown($event,input)"></textarea>
<button v-on:click="add(input)">Apply</button>
</div>
</script>
I have defined component method called .getGroupName() which relays on other function called .qualifier() that can be set over props.
My problem: once I add any tags to collection (.items) when i type anything into textarea for each keydown .getGroupName() seems to be called. It looks like entering anything to textarea results all component rerender?
Do you know how to avoid this behavior? I expect .getGroupName to be called only when new tag is added.
Heres the full code:
https://codepen.io/anon/pen/bKOJjo?editors=1011 (i have placed debugger; to catch when runtime enters .qualifier().
Any help appriciated.
It Man
TL;DR;
You can't, what you can do is optimize to reduce function calls.
the redraws are dynamic, triggered by data change. because you have functions (v-model and #keydown) you will update the data. The issue is that when you call a function: :data-group="getGroupName(item)" it will execute every time, because it makes no assumptions on what data may have changed.
One way of dealing with is is setting groupName as a computed key-val object that you can look up without calling the function. Then you can use :data-group="getGroupName[item]" without calling the function on redraw. The same should be done for v-html="tagRender(item)"
Instead of trying to fight how the framework handles data input events and rendering, instead use it to your advantage:
new Vue({
el: '#app',
template: '#example',
data() {
return {
someInput: '',
someInputStore: []
};
},
methods: {
add() {
if (this.someInputStore.indexOf(this.someInput) === -1) {
this.someInputStore.push(this.someInput);
this.someInput = '';
}
},
}
});
<html>
<body>
<div id="app"></div>
<template id="example">
<div>
<textarea v-model="someInput" #keyup.enter.exact="add" #keyup.shift.enter=""></textarea>
<button #click="add">click to add new input</button>
<div>
{{ someInputStore }}
</div>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
</body>
</html>
Event modifiers modifying
In the example, you can see that I am using 4 different event modifiers in order to achieve the desired outcome, but I will focus on the combination of them here:
#keyup.enter.exact - allows control of the exact combination of system modifiers needed to trigger an event. In this case, we are looking for the enter button.
#keyup.shift.enter - this is the interesting bit. Instead of trying to hackily prevent the framework from firing on both events, we can use this (and a blank value) to prevent the event we added into #keyup.enter.exact from firing. I must note that ="" is critical to the whole setup working properly. Without it, you aren't giving vue an alternative to firing the add method, as shown by my example.
I hope this helps!