Dynamic rendering of the html is not working vue js - vue.js

new Vue({
el: '#application',
data: {
currencies: [
{
'name': 'Dollar',
'sign': '$'
}, {
'name': 'Euro',
'sign': '€'
}, {
'name': 'Pound',
'sign': '£'
}, {
'name': 'Cent',
'sign': '¢'
}
]
}
});
<select class="custom-select" v-model="quotationForm.currency">
<option v-for="currency in currencies" v-bind:value="currency.sign">
<span v-html="currency.sign"></span>
{{ currency.name }}
</option>
</select>
Currency sign can not been rendered on the select box.
But when i try to make statis it's works fine as per given below...
<select class="custom-select" v-model="quotationForm.currency">
<option v-for="currency in currencies" v-bind:value="currency.sign">
€
{{ currency.name }}
</option>
</select>
Whyv-html is not works in the select box? have any suggestion
Thank You.

I tested it on my own and it's working: Link
<template>
<select class="custom-select" v-model="quotationForm.currency">
<option :key="index" v-for="(currency, index) in currencies" v-bind:value="currency.sign">
<span v-html="currency.sign"></span>
{{ currency.name }}
</option>
</select>
</template>
<script>
export default {
data() {
return {
quotationForm: {
currency: null
},
currencies: [
{
'name': 'Dollar',
'sign': '$'
}, {
'name': 'Euro',
'sign': '€'
}, {
'name': 'Pound',
'sign': '£'
}, {
'name': 'Cent',
'sign': '¢'
}
]
}
}
}
</script>

Related

Emitting two properties from child to parent

Can anyone help with this problem? How can I emit two properties from child component to parent on select input change? I can submit the value, see below, but would like to emit the value and the name property of segmentLocations object. This is the child component:
<template>
<div class="container">
<div>
<select v-model="selectedSegmentValue" v-on:change="$emit('selectLocation', $event.target.value)">
<option selected value="">Choose your location...</option>
<option v-for="segmentLocation in segmentLocations"
:value="segmentLocation.value"
:key="segmentLocation.value">
{{ segmentLocation.name }}>
</option>
</select>
</div>
</div>
</template>
<script>
export default {
data() {
return {
segmentLocations: [
{ value: "Residential", name: 'Residential building' },
{ value: "Workplace", name: 'Workplace' },
{ value: "Hospitality", name: 'Hospitality or Retail' },
{ value: "Real Estate", name: 'Real Estate' },
{ value: "Commercial Parking", name: 'Commercial Parking' },
{ value: "Fleets", name: 'Fleets' },
{ value: "Cities & Governments", name: 'Cities & Governments' },
{ value: "Corridor", name: 'Highway, Corridor or Petrol Station' }
],
}
}
};
</script>
And this is the parent:
<template>
<Segments
v-on:selectLocation="quote.selectedSegmentValue = $event"
:selectedValue="quote.selectedSegmentValue">
</Segments>
</template>
<script>
export default {
data() {
return {
quote: {
selectedSegmentValue: "",
selectedSegmentName: ""
},
};
},
</script>
I think the existing answers and mine share a similar technique, but I created a couple of simplified sample components based on your components.
Child component:
<template>
<div class="emit-two-properties">
<div class="form-group">
<label for="segment-location">Segment Location</label>
<select class="form-control" id="segment-location"
v-model="segmentLocation" #change="selectSegmentLocation">
<option v-for="(segLoc, index) in segmentLocations" :key="index"
:value="segLoc">{{ segLoc.name }}</option>
</select>
</div>
</div>
</template>
<script>
export default {
data() {
return {
segmentLocation: {},
segmentLocations: [
{ value: "Residential", name: 'Residential building' },
{ value: "Workplace", name: 'Workplace' },
{ value: "Hospitality", name: 'Hospitality or Retail' },
{ value: "Real Estate", name: 'Real Estate' },
{ value: "Commercial Parking", name: 'Commercial Parking' },
{ value: "Fleets", name: 'Fleets' },
{ value: "Cities & Governments", name: 'Cities & Governments' },
{ value: "Corridor", name: 'Highway, Corridor or Petrol Station' }
],
}
},
methods: {
selectSegmentLocation() {
this.$emit('select-segment-location-event', this.segmentLocation);
}
}
}
</script>
Parent component:
<template>
<div class="parent">
<h4>Parent.vue</h4>
<div class="row">
<div class="col-md-6">
<form #submit.prevent="submitForm">
<emit-two-properties #select-segment-location-event="updateSegmentLocation" />
<button class="btn btn-secondary">Submit</button>
</form>
<p><span>Selected Segment Location Value:</span>{{ segmentLocation.value }}</p>
<p><span>Selected Segment Location Name:</span>{{ segmentLocation.name }}</p>
</div>
</div>
</div>
</template>
<script>
import EmitTwoProperties from './EmitTwoProperties'
export default {
components: {
EmitTwoProperties
},
data() {
return {
segmentLocation: {}
}
},
methods: {
updateSegmentLocation(segLoc) {
this.segmentLocation = segLoc;
}
}
}
</script>
you can create a method to get name and value from event.target (remove value from the end of child emit):
changeSelectedSegment(selected){
this.selectedSegmentName = selected.name
this.selectedSegmentValue = selected.value
}
in the parent change v-on:selectLocation to v-on:selectLocation="changeSelectedSegment($event)"
you can define a method like this (this method emit an object with name and value properties to parent
)
methods: {
selectLocation(event){
if(event.target.value !== ''){
const item = this.segmentLocations.find( item => item.value === event.target.value)
this.$emit('selectLocation', {
name: item.name,
value: event.target.value
})
}
}
},
and change this line :
<select v-model="selectedSegmentValue" v-on:change="$emit('selectLocation', $event.target.value)">
to this:
<select v-model="selectedSegmentValue" v-on:change="selectLocation">

Wrong parameter received in function call

Why do I receive subject (object that I want) on first item but MouseEvent from all other subject changes?
<template v-for="subject in subjects">
<select v-model="subject.name" class="form-control" #change="setNote(subject)">
<option v-for="vsub in validSubjects" :value="vsub.id_subject">{{ vsub.name }}</option>
</select>
</template>
This works for me:
var app = new Vue({
el: '#app',
data: {
message: 'Choose a subject: ',
subjects: [{
name: "Maths"
}, {
name: "Science"
}],
validSubjects: [{
id_subject: "1",
name: "Maths"
}, {
id_subject: "2",
name: "Science"
}, {
id_subject: "3",
name: "English"
}]
},
methods: {
setNote(subject) {
console.log(subject);
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
{{ message }}
<template v-for="subject in subjects">
<select v-model="subject.name" class="form-control" #change="setNote(subject)">
<option v-for="vsub in validSubjects" :value="vsub.id_subject">{{ vsub.name }}</option>
</select>
</template>
</div>

Using a filter inside a v-for?

Inside a v-for loop how can I apply a filter to the text? My inline template:
<select>
<option v-for="(item, index) in items" :key="index" :value="item.id" v-text="item.name | capitalize"></option>
</select>
I get multiple warnings Property or method "capitalize" is not defined on the instance but referenced during render. Even though the filter is defined.
So I presume its some sort of scope issue in the loop? How can this be solved?
As Vue Guide: Filters mentions, Filters are usable in mustache interpolations and v-bind expressions, not including the directives.
For your codes,
Solution 1 will be mustache interpolations.
Vue.filter('global-capitalize', function (value) {
return value.toUpperCase()
})
new Vue({
el: "#app",
data: {
items: [
{ text: "Learn JavaScript", id: 1 },
{ text: "Learn Vue", id: 2 },
{ text: "Play around in JSFiddle", id: 3 },
{ text: "Build something awesome", id: 4 }
]
},
filters: {
capitalize: function (name) {
return name.toUpperCase()
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Todos:</h2>
<select>
<option v-for="(item, index) in items" :key="index" :value="item.id">
{{item.text | capitalize}}
</option>
</select>
<select>
<option v-for="(item, index) in items" :key="index" :value="item.id">
{{item.text | global-capitalize}}
</option>
</select>
</div>
Another solution is uses computed properties or methods.
new Vue({
el: "#app",
data: {
items: [
{ text: "Learn JavaScript", id: 1 },
{ text: "Learn Vue", id: 2 },
{ text: "Play around in JSFiddle", id: 3 },
{ text: "Build something awesome", id: 4 }
]
},
computed: {
computedItems: function () {
return this.items.map(item => {
return {text: item.text.toUpperCase(), id: item.id}
})
},
},
methods: {
filterFunc: function (name) {
return name.toUpperCase()
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select>
<option v-for="(item, index) in computedItems" :key="index" :value="item.id" v-text="item.text">
</option>
</select>
<select>
<option v-for="(item, index) in items" :key="index" :value="item.id" v-text="filterFunc(item.text)">
</option>
</select>
</div>

'[Object object]' is displayed instead of label in Vue.js datalist

I'm using <datalist> drop-down menu to display group names in our project.
<data-list
ref="groupName"
name="groupName"
label="Groups: "
:options="groupList"
></data-list>
.....
methods:{
groupList(){
return this.$store.getters['Groups/getGroups']
}
}
But this is displayed in my UI:
I actually want the dropdown to display the label field, which is a group name, and I'll get the value of it. The structure of returned value looks like this:
[
{label: "test", value: 14},
{label: "Test1", value: 16},
{label: "Test2", value: 17},
{label: "Test3", value: 18},
]
It seems the bug is in your data-list component. Most likely you have something like this:
<!-- XXX: DON'T DO THIS -->
<option v-for="option in options" :value="option">{{option}}</option>
Vue.component('data-list', {
props: ['label', 'options'],
template: `
<div>
<label for="myinput">{{label}}</label>
<input id="myinput" list="mydata">
<datalist id="mydata">
<!-- XXX: DON'T DO THIS -->
<option v-for="option in options" :value="option">
{{option}}
</option>
</datalist>
</div>`,
});
new Vue({
el: '#app',
data() {
return {
groupList: [
{label: "test", value: 14},
{label: "Test1", value: 16},
{label: "Test2", value: 17},
{label: "Test3", value: 18},
]
};
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<data-list label="Groups: " :options="groupList"></data-list>
</div>
But you actually need to set the value of <option> to option.value and its inner text to {{option.label}} (matching your item's data structure):
<option v-for="option in options" :value="option.value">{{option.label}}</option>
Vue.component('data-list', {
props: ['label', 'options'],
template: `
<div>
<label for="myinput">{{label}}</label>
<input id="myinput" list="mydata">
<datalist id="mydata">
<option v-for="option in options" :value="option.value">
{{option.label}}
</option>
</datalist>
</div>`,
});
new Vue({
el: '#app',
data() {
return {
groupList: [
{label: "test", value: 14},
{label: "Test1", value: 16},
{label: "Test2", value: 17},
{label: "Test3", value: 18},
]
};
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<data-list label="Groups: " :options="groupList"></data-list>
</div>
you can to use like this in html and js.
actually following code is not a component.
sample HTML code
<datalist id="browsers">
<option v-for="lst in groupList" v-bind:value="lst">{{lst.label}}</option>
</datalist>
sample Vue.js code
data:{
groupObj: {},
groupList: []
},
methods:{
groupList(){
this.groupList = this.$store.getters['Groups/getGroups'];
},
},
mounted(){
this.groupList();
}
I understand the question as "How to work with objects in datalists in vue.js"
what are datalists?
datalists provides just templates to fill other controls.
mostly used with text input to provide combobox functionallity (allow also new content to be selected)
At this time implementation in browsers vary greatly, so better to just rely on basic label rendering (don't use value, since browsers handle it differently)
using it in vue with objects
Idea is to use strings and check on every input change if we have a perfect match. Using :value will show the id in chrome, which is probably not what you want. This doesn't work with same-named labels, but then again, such an input makes little sense in that case.
Vue.component('test-data-list', {
props: ['label', 'options', 'value'],
template: `
<div>
<label for="myinput">{{label}}</label>
<input id="myinput" list="data" #change="change" :value="getValue">
<datalist id="data">
<option v-for="option in options">
{{option.label}}
</option>
</datalist>
</div>`,
computed: {
getValue() {
return this.value ? this.value.label : '';
}
},
methods: {
change(e) {
let value = e.currentTarget.value;
if (value) {
let sel = this.options.filter(c => c.label == value);
if (sel.length == 1) {
this.selection = sel[0];
} else {
this.selection = {
label: value,
isNew: true
}
}
} else {
this.selection = undefined;
}
this.$emit('input', this.selection)
}
}
});
new Vue({
el: '#app',
data() {
return {
result: undefined,
groupList: [{
label: "something",
id: 1
},
{
label: "this too",
id: 2
},
{
label: "something different",
id: 3
}
]
};
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
Selected:
<span v-if="result">
"{{ result.label }}"
<span v-if="result.isNew">New!</span>
<span v-else> old object with id:{{result.id}}</span>
</span>
<span v-else>nothing</span>
</div>
<test-data-list label="Select" :options="groupList" v-model="result"></test-data-list>
</div>

How to wire a conditional block in option HTML element using vue 2

I'm new to vue and have a problem with a conditonal rendering (v-if) in an option element.
when i have an empty array i would like to show an disabled option otherwise it show me the countries. Like in this description https://v2.vuejs.org/v2/guide/conditional.html but unfortunately this is not working on an option HTML element. What i'm missing ?
new Vue({
el: '#app',
data: {
selected: '',
optionAvailable: true,
countries: [
//{ name: 'USA', population: '300M' },
//{ name: 'Canada', population: '100M' },
//{ name: 'Germany', population: '80M' },
]
},
created() {
if(!this.countries.length > 0) {
return this.optionAvailable = false;
}
return true;
},
methods: {
onChange(event) {
this.selected = event.value;
}
}
})
html:
<div id="app">
<select #change="onChange($event.target)">
<option v-if="optionAvailable" v-for="(country,index) in countries" :value="country.population">{{ country.name }}</option>
<option v-else disabled>-</option>
</select>
<br>
<span>{{ selected }}</span>
</div>
here jsfiddle:
https://jsfiddle.net/50wL7mdz/434002/
Try this:
template
<div id="app">
<select #change="onChange($event.target)">
<option v-if="countries.length" v-for="(country,index) in countries" :value="country.population">{{ country.name}}</option>
<option v-else>----</option>
</select>
<span>{{ selected }}</span>
</div>
script
new Vue({
el: '#app',
data: {
selected: '',
optionAvailable: true,
countries: [
{ name: 'USA', population: '300M' },
{ name: 'Canada', population: '100M' },
{ name: 'Germany', population: '80M' } ]
},
methods: {
onChange(event) {
this.selected = event.value;
}
}
})
You don't need the created hook. You can tell v-if to look at the length of countries directly.
https://jsfiddle.net/z4mu8L9e/8/
try this template
<div id="app">
<select #change="onChange($event.target)" :disabled="!countries.length">
<option v-if="!countries.length" value="">No available countries</option>
<option v-for="(country,index) in countries" :value="country.population">{{ country.name }}</option>
</select>
<br>
<span>{{ selected }}</span>
</div>
Script
new Vue({
el: '#app',
data: {
selected: '',
countries: []
},
methods: {
onChange(event) {
this.selected = event.value;
}
}
})