how to bind v-model to a specific array element in vuejs? - vuejs2

I would like to bind v-model to a specific array element like the following, is this possible?
<input v-model='item[1]' />
Thanks

Yes, that is the right way:
var vm = new Vue({
el: '#vue-instance',
data: {
items: ["Item1", "Item2"]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
<div id="vue-instance">
<input v-model='items[0]'/>
<div v-for="item in items">
{{item}}
</div>
</div>

Related

using vuejs how do i get the value of content in a div and display inside of the model

I am using vuejs and I want to get the value of a div and display it inside of the model. Issue is i Cannot use the recommended refs because I in reality cant modify the html. Does anyone have a basic solution where I can leverage vuejs and push the content to the model where location is?
new Vue({
el: "#app",
data: {
location:''
},
methods: {
test:function(){
if (!this.$refs.myRef) {
console.log("This doesn't exist yet!");
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="FilePathPlaceholder" class="d2l-placeholder d2l-placeholder-live" aria-live="assertive">
<div class="d2l_1_234_979">
<div class="d2l_1_235_849 d2l_1_236_43 d2l-inline">
<span class="d2l-textblock"></span>
<span
class="d2l-textblock d2l_1_237_505 d2l_1_238_137"
id="d2l_1_233_684"
title="/content/Stuff/12183-CC-242/">
/content/Stuff/
<strong>12183-CC-242</strong>/
</span>
<input type="hidden" name="FilePath" id="FilePath" value="/content/Stuff/12183-CC-242/">
</div>
<div class="d2l_1_237_505 d2l-inline">
<span class="d2l-validator" id="d2l_1_239_562"></span>
</div>
</div>
</div>
</div>

Range slider how to make step size change in vue.js

<template>
<Slider v-model="[0, 2500]" :min="0" :max="2500" :step="50" />
</template>
I need the steps to be like [50, 100, 250] but not the single value i.e 50
Can anybody help me with this
You can use a simple input range with your desired values. Only the v-model is important to create the two-way-data-binding.
new Vue({
el: '#app',
data: {
selectedValue: 0
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id='app'>
<input type="range" min="0" max="2500" step="50" v-model="selectedValue">
<p>selected value: {{ selectedValue }}</p>
</div>

Adding a component by clicking a button

Vue.component('component-a', {
template: '<h3>Hello world!</h3>'
})
new Vue({
el: "#app",
data: {
arr: []
},
methods: {
add(){
this.arr.push('component-a');
console.dir(this.arr)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<component-a></component-a>
<hr>
<button #click="add">Add a component</button>
<ul>
<li v-for="component in arr"> {{ component }} </li>
</ul>
</div>
I want to insert a component a lot of times to the page by clicking a butoon, but instead of this only a component`s name is inserted. How to add a component itself?
In your code the double curly braces do not reference the component itself but just the string you added with this.arr.push('component-a'); hence just the string being displayed.
If you would like this string to call the actual component you could use dynamic components.
Replacing {{ component }} with <component :is="component"/> would achieve the effect I think you're looking for.
However if you're only going to be adding one type of component I would consider adding the v-for to the component tag itself like so:
<component-a v-for="component in arr/>
Use the component element to render your component dynamically.
The usage is very simple: <component :is="yourComponentName"></component>
The ":is" property is required, it takes a string (or a component definition).
Vue will then take that provided string and tries to render that component. Of course the provided component needs to be registered first.
All you have to do is to add the component tag as a child element of your list tag:
<li v-for="component in arr">
<component :is="component"></component>
</li>
Vue.component('component-a', {
template: '<h3>Hello world!</h3>'
})
new Vue({
el: "#app",
data: {
arr: []
},
methods: {
add() {
this.arr.push('component-a');
console.dir(this.arr)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<component-a></component-a>
<hr>
<button #click="add">Add a component</button>
<ul>
<li v-for="component in arr">
<component :is="component"></component>
</li>
</ul>
</div>

Conditional a href in Vuejs

I am rendering a list of store titles in VueJS, some of them have a url property, some of them don't. If the title has a url, I want to add a a href property:
<div v-for="(store, index) in stores">
<span v-if="store.link"><a :href="store.link" target="_blank">{{ store.title }}</a></span>
<span v-else="store.link">{{ store.title }}</span>
</div>
This works, but the code looks duplicated. Is there anyway to simplify the code further?
you can use component tag:
var app = new Vue({
el: '#app',
data () {
return {
stores: [
{title:'product1',link:'/products/222'},
{title:'product2'},
{title:'product3',link:'/products/333'},
{title:'product4'}
]
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<div v-for="(store, index) in stores">
<component :is="store.link?'a':'span'" :href="store.link || ''" target="_blank">{{store.title}}
</component>
</div>
</div>
I'd remove the first span element, as it's not necessary. Also, the v-else does not need the conditional statement (it's not v-else-if):
new Vue({
el: '#app',
data: {
stores: [
{ link: 'foo', title: 'foo-text' },
{ title: 'bar-text' }
]
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div v-for="(store, index) in stores" :key="index">
<a v-if="store.link" :href="store.link" target="_blank">{{ store.title }}</a>
<span v-else>{{ store.title }}</span>
</div>
</div>
You can use dynamic arguments in vue3
https://v3.vuejs.org/guide/template-syntax.html#dynamic-arguments
<a v-bind:[attributeName]="url"> ... </a>
or binding an object of attributes
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>

Any easier way to access nested object properties in Vue template?

It's convenient to group data into nested object properties. By doing this, we don't have to collect properties from the data field into an entity for later use. As in the following example,
var demo = new Vue({
el: '#demo',
data: {
level1: {
level2: {
level3_1: 'Hello',
level3_2: 'world'
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="demo">
<div class="person">
<h3>{{ level1.level2.level3_1 }}</h3>
<p>{{ level1.level2.level3_2 }}</p>
</div>
</div>
However, it's really overkill having to type the "level1.level2" prefix in order to get to the level3_x field. It'll be very cumbersome if there're loads of level3 fields.
I wonder if there is any way that I can save the work for typing level1.level2 over and over again. Does the template have any syntax so that some section is under the scope of "level1.level2"? Does Vue provide any support so that in this case the prefix "level1.level2" is assumed?
There are a couple of options.
1. Use v-for
Everything inside the v-for block is scoped to the level that you're iterating over. Do it like this:
var demo = new Vue({
el: '#demo',
data: {
level1: {
level2: {
level3_1: 'Hello',
level3_2: 'world'
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="demo">
<div class="person">
<template v-for="(l2prop, l2propName) in level1">
<h3>{{ l2prop.level3_1 }}</h3>
<p>{{ l2prop.level3_2 }}</p>
</template>
</div>
</div>
2. Use a component
Components get a subset of their parent's data, so they're automatically scoped. Do it like this:
Vue.component( "person", {
props: ['data'],
template: '<div class="person"><h3>{{ data.level3_1 }}</h3><p>{{ data.level3_2 }}</p></div>'
});
var demo = new Vue({
el: '#demo',
data: {
level1: {
level2: {
level3_1: 'Hello',
level3_2: 'world'
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="demo">
<person v-bind:data="level1.level2"></person>
</div>
The example of #jason-smith is almost right. v-for is used for arrays or lists. To make it work is necessary to put your object in list.
Following his example the better approach would be
var demo = new Vue({
el: '#demo',
data: {
level1: {
level2: {
level3_1: 'Level 3_1',
level3_2: 'Level 3_2'
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div class="person">
<template v-for="level2Obj in [level1.level2]">
<h3>{{ level2Obj.level3_1 }}</h3>
<p>{{ level2Obj.level3_2 }}</p>
</template>
</div>
</div>
There are serval ways:
Use a method that gets the same level
methods:{
getLvl3: function(nr){
return this["level"+nr]["level"+nr]["level3_"+nr];
}
{{ getLvl3(1) }}
Iterate over with v-for v-for docu
example:
<div id="demo">
<div class="person">
<template v-for="(lvl2, key) in level1">
<template v-for="(lvl3, key) in lvl2">
<h3 v-if="key === 'level3_1'>{{ lvl3 }}</h3>
<p v-if="key === 'level3_2'">{{ lvl3 }}</p>
</template>
</template>
</div>
</div>
bind to variable that is defined outside of vue:
var nested = { level1: { level2: { level3_1: 'Hello', level3_2: 'world' }}
and inside of vue component or instance:
data:{
level2: nested.level1.level2,
}
<div id="demo">
<div class="person">
<h3>{{ level2.level3_1 }}</h3>
<p>{{ level2.level3_2 }}</p>
</div>
</div>