Vue-select bind v-model to save value, not label - vuejs2

I am new to VueJs (currently working on: 2.5.8) and trying to implement vue-select.
I have successfully integrated the plugin in my app and using it with:
<v-select :options="oData" v-model="selected">
new Vue({
el: "#app",
data: {
oData: ["foo", "bar"],
selected: null
}
});
This seems to work fine, but whenever I select foo or bar from the options, the selected contains foo/bar based on selected, whereas I want to store it's respective index, for ex: if foo is selected, the selected should contain 0 instead of foo.
Can anyone please help me to achieve that?

The following code worked for me.
oData = [{label:"foo", value:"1"},{label:"bar", value:"2"}]
<v-select
v-model="selected"
:items="oData"
item-text="label"
item-value="value"
>
</v-select>

Related

Generate Vue Component with vanilla JS

I am currently using the bootstrap table component to display a list (bootstrap-table.com)
This component (or jQuery plugin wrapped within a vue component) has a formatter for each column.
example with source code: https://examples.bootstrap-table.com/#welcomes/vue-component.html#view-source
I need to build a more complex set of links which involve some js processing that could easily be done with vue.
Instead of the formatter returning the <a> tag I would like to return the contents of a <component>. I have tried this but haven't been able to render a component.
I'm almost sure this is impossible because the child component is not previously binded which means the component won't be "reactive".
As an alternative I can build a js function that generates all the required links.
Another phrasing for this question would be: Is there any possibility to generate a vue component from vanilla js?
The above was not possible the way was tried because the components cannot be simply rendered like html tags as they can have methods and computed data therefore they must be compiled.
It looks like the solution for the above situation is using the Vue.compile() method:
const template = `
<ul>
<li v-for="item in items">
{{ item }}
</li>
</ul>`;
const compiledTemplate = Vue.compile(template);
new Vue({
el: '#app',
data() {
return {
items: ['Item1', 'Item2']
}
},
render(createElement) {
return compiledTemplate.render.call(this, createElement);
}
});
Demo:
https://codepen.io/couellet/pen/ZZNXzy
Demo reference:
https://snipcart.com/blog/vue-render-functions
Vue docs:
https://v2.vuejs.org/v2/api/#Vue-compile

How to add different components to the page on-the-fly with Vue.js

My goal is to allow the user to dynamically build a form from different components, based on what they choose in a select element. For example, they can choose to add a Heading, then maybe a Paragraph, then another Heading, etc. Each "part" is a separate Component.
I know this sort of thing has been asked before, but I'm only day 2 into Vue and I think I'm 90% of the way there - I'm just missing something. What I believe I'm stuck on is how to add a component to my app's data to allow Vue to render it out.
Here is the relevant markup:
<div id="creator">
<template v-for="part in existingParts">
<component :is="part"></component>
</template>
<select class = "custom-select" id = "new-part-chooser" v-model="newPart" v-on:change="addPart">
<option disabled value = "">Add a new part</option>
<option
v-for="part in possibleParts"
v-bind:value="part.toLowerCase()"
>{{ part }}</option>
</select>
<?php
// These simply bring in the templates for the components
// I know this isn't standard practice but... one thing at a time
include 'component-heading.html';
include 'component-paragraph.html';
?>
</div>
and my javascript file:
Vue.component("part-heading",{
data:function(){
return {
text: ""
}
},
template:"#component-heading-template"
});
Vue.component("part-paragraph",{
data:function(){
return {
text: ""
}
},
template:"#component-paragraph-template"
});
const Creator = new Vue({
el:"#creator",
data:{
newPart:"",
possibleParts:[
"Heading",
"Paragraph"
],
existingParts:[]
},
methods:{
addPart:function(e){
/*** This is where I'm stuck - what do I push here? ***/
this.existingParts.push();
}
}
});
I've read through the docs and Google'd the hell out of the topic, but every setup seems to be just different enough that I can't figure out how to apply it.
I was missing the fact that in the markup, the :is directive causes Vue to create a component that matches the name of the element in existingParts. So push()-ing "part-heading" into existingParts causes Vue to render an instance of the "part-heading" component.
The updated, working code is:
this.existingParts.push('part-'+this.newPart);

Vuejs problem ; How to bind new elements added to DOM?

I Want to add new element to the DOM after new Vue instance created.
I know I can re initiate the instance of vue but it seems it is not good idea because vue have to re render all elements again. So is there a method to bind just new element to the data scope?
<body>
<div id="app">
<span>{{ a }}<span>
<div id="newElem"></div>
</div>
</body>
<script>
$(document).ready(function () {
var mainApp = new Vue({
el: "#app",
data: {
"a": "aa",
"b": "bb"
}
});
$("#newElem").html("<span>{{ b }}</span>")
});
</script>
This code renders {{ b }} unbinded. I am looking for a method for preventing this.
Thanks
Have you tried something like this?
<div v-html="newElem"></div>
el: "#app",
data: {
"a": "aa",
"b": "bb"
},
created() {
this.newElem = "<span>{{ b }}</span>";
}
It's really hard to tell your ultimate goal here but I'll take a shot.
Ideally, you wouldn't touch the DOM, you'd want to update the data and let Vue handle the DOM for you.
I think you want to initialize b as undefined and set that when you're ready for it to be displayed.
data: {
a: 'aa',
b: undefined,
}
Then in your template you can have something like this:
<span v-if="b">{{ b }}</span>
This way the span won't display until b is truthy.
Then, later, when b is ready, you would mainApp.b = 'bb'.
Here's a quick demo: http://jsfiddle.net/crswll/vtu8nzea/1/
If you make add a more complete use case I can likely help further.
Also, this answer might help as well. It's kind of like the next level of this thinking: Vuejs: v-model array in multiple input

Does Vue have bilateral bind?

<p contenteditable="true" v-bind="message"></p>
Object #message does not change when I edit the HTML element. Is there any simple way to do this using Vue.js?
Unfortunately, contenteditable doesn't work with Vue bindings such as v-model, it's recommended that you use a library such as medium.js to build your own component.
However, if you're just trying to do something simple and keep the data in sync you can probably do that yourself:
View Model
new Vue({
el: '#app',
methods: {
updateMessage() {
this.message = this.$refs.message.innerText;
}
},
watch: {
message() {
this.$refs.message.innerText = this.message;
}
},
data: {
message: 'Hello'
}
})
HTML
<p ref="message" contenteditable="true" #keyup="updateMessage" class="editable">{{message}}</p>
 
As you can see you have to deal with updating the DOM yourself when using contenteditable. What I'm actually doing here is using a ref to target the contenteditable, so I can get the inner text via this.$refs.message.innerText. I've then added a #keyup event which calls the updateMessage method to update the message data property. I've then added a watcher which reverses this process, so when message is updated it updates the contenteditable.
Here's the JSFiddle: https://jsfiddle.net/3ngc9486/
Yes it has a two-way binding directive v-model, but it works only with input elements. So, instead of using a p element and handling that with complex JS, use a textarea with v-model and it will work out of the box.
<textarea v-model="message"></textarea>
here is an example.

I am really confused with the radio input in Vue.js

From the Vue guide, I saw these things:"For radio, checkbox and select options, the v-model binding values are usually static strings (or booleans for checkbox):" and
<!-- `picked` is a string "a" when checked -->
<input type="radio" v-model="picked" value="a">
But when I try to render picked in the tag , it does not work. why?
Here's my code.(in this case, it's one)
When I click the radio, it does not reflect in the tag span.
Your missing data, try:
new Vue({
el:'#app',
data: {
picked: 'One'
}
})
Example: http://codepen.io/anon/pen/NpPmgp
You have to add data as well in the vue instance:
new Vue({
el:'#app',
data: {
picked: 'Two'
}
})
Check this:
http://codepen.io/anon/pen/XMJQRB