I have a component, which listens out for the value of the selection from the dropdown and outputs it within a child component. The issue is is that the $event value is a ID number, I require a string which is the same as is outputted via '{{(type.name)}}'.
I have changed the input value to type.name, but this causes issues with other components in the app that rely on the value being an ID integer.
Is there a way to change the value being captured, to that of the string value being interpolated in {{(type.name)}} ?
NOTE: I have returned the this.event object to me, and the text value of the selection is not a property within it.
TEMPLATE:
<b-select
:v-model="documentType"
#input="updateModel"
>
<optgroup
v-for="group in allDocumentTypeGroups"
:key="group.id"
:label="t(group.name)"
>
<option
v-for="type in group.documentTypes"
:key="type.id"
:value="type.id"
>
{{(type.name)}}
</option>
</optgroup>
</b-select>
METHODS:
methods: {
updateModel($event) {
this.storage_Selection.push($event);
this.$store.commit('addDocumentType', this.storage_Selection);
}
}
Use the ID to look up the name from this.groups in your updateModel handler. Something like (untested):
methods: {
updateModel(id) {
const name = this.group.documentTypes.find(type => type.id == id)
this.storage_Selection.push(name);
this.$store.commit('addDocumentType', this.storage_Selection);
}
}
Related
I am trying to set the disabled property on a text field via checkbox. I'm referencing this item, but none of the solutions are working for me.
My text field and checkbox are as follows:
<input
type="checkbox"
class="form-check-input"
v-model="formData.useSystemSetting"
>
<input
type="text"
class="form-control"
:class="hasError('maxCount') ? 'is-invalid' : ''"
placeholder="Enter the Maximum Count"
v-model="formData.maxCount"
:disabled = "isDisabled"
>
My computed property is:
computed:{
isDisabled: function() {
this.useSystemSetting = this.useSystemSetting == true?false:true
return this.useSystemSetting;
},
I'm also setting useSystemSettings in the data section to true because if I don't it doesn't get populated. When I add a breakpoint to the computed property, it's only getting hit on the page load, but not after.
It's not allowed to mutate other properties inside the computed property, you should only do some process and return a value:
computed:{
isDisabled: function() {
return this.useSystemSetting ? false : true;
}
}
You shouldn't mutate data inside a computed property.
A computed property is used whenever you need to use logic for getting a value which includes reactive data, as you'd find here.
You could try something like:
computed:{
isDisabled: function() {
return !this.formData.useSystemSetting;
}
}
Presuming that the formData object will not be null at this point.
To prevent that, you could also use something like:
return ((this.formData || {}).useSystemSetting || true) ? false : true;
I'm trying to get a select element bound to a value for a custom object. The crux here is that the object property in question has a custom getter. The value is set as a number, but when accessed returns an associated value as a string. Why I do this is a long story.
So I have an object of key-value pairs making some options:
<select v-model="myObject.myProperty">
<option v-for="v, k in myOptions" :key="k" :value="k">{{v}}</option>
</select>
{{myObject.myProperty}} //this line prints out the correct value
But the options are not showing as selected. The value is updated for myObject.myProperty and it returns what I expect. I suspect that behind the scenes, it's correctly assigning k to my custom object, but that because it returns a different string value, Vue can't inherently figure out which option to mark 'selected'.
Manually adding :selected does not help:
<option v-for="v, k in myOptions" :key="k" :value="k" :selected="v === myObject.myProperty">{{v}}</option>
I also tried to manually bind the select instead of using the v-model attribute, also no:
<select :value="myObject.myProperty" #input="myObject.myProperty = $event.target.value"
Is there an alternative way to wire up a select/option situation? If not, building a custom component with faux-select functionality is my next step.
For clarity, myOptions is a key-value like this
{
0 : 'Option 1',
1 : 'Option 2',
}
But myObject has special setters that take and remember the key, then also a special getter than returns the value from myOptions.
So then:
myObject.myProperty = 0;
console.log(myObject.myProperty) //logs 'Option 1'
When when I set the value to the key (k) I get back the corresponding value when the option is selected and the value of 'myObject.myProperty' is what I expect. Example: I pick 'Option 1' from the drop-down, which has a value of 0 derived from the key k.
However, although myObject.myProperty has the value I want, I can't get Vue to display the the actual html option as selected, probably because the value returned by myObject.myProperty is 'Option 1' and not 0
Alright, the actual answer:
<select #input="myObject.myProperty = $event.target.value">
<option v-for="v, k in myOptions" :selected="myObject.myProperty === v" :key="k" :value="k">{{v}}</option>
</select>
v-model won't work here because it simply doesn't care that you've manually applied selected: it will always try to match the option value to the the v-model property value. As this object takes one value with a setter and returns another with a getter, these will never align.
Instead, manually assign the value to the object with #input and match the value from the getter to the value in the options for selected.
Not sure I understand your question properly or not. Hence, adding my input on your requirement below.
As myObject.myProperty returning the value you passed in the select and as per your code you are passing the index as value.
Hence, while comparing in :selected both LHS and RHS should contain index of the item you passed.
Working Demo :
const app = new Vue({
el: '#app',
data() {
return {
myOptions: [{
id: 1,
name: 'alpha'
}, {
id: 2,
name: 'beta'
}, {
id: 3,
name: 'gama'
}],
myObject: {
myProperty: ''
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="myObject.myProperty">
<option v-for="(item, index) in myOptions" :selected="myObject.myProperty === item.id" :key="item.id" :value="item.id">{{item.name}}</option>
</select>
{{myObject.myProperty}}
</div>
UPDATE Based on the newly provided information.
In Template:
<select v-model="selectedOption">
<option v-for="(v, k) in options" :key="k" :value="k">
{{ v }}
</option>
</select>
In JS
data() {
return {
selectedOption: null,
options: {
0: 'Option 1',
1: 'Option 2',
},
};
}
By setting selectedOption with the key of options will correctly display the selected option.
Here is a link to a working example using your data structure. It contains two selects both using the same object for its data source. One with a default selection. the other without.
https://stackblitz.com/edit/vue-efekym?file=src/App.vue
THIS IS NOW OUTDATED BASED ON THE LATEST INFO
Based on the logic in your further examples I think the problem is within conflating your k & v variables in your loop. Although it is hard to tell because there isn't any sample data or a complete isolated component outlying the behavior.
However in your later examples you have:
<option v-for="v, k in myOptions" :key="k" :value="k" :selected="v === myObject.myProperty">{{v}}</option>
I am inferring that you believe that myObject.myProperty is holding the value from variable v, when in fact you are setting the value as variable k as witnessed in :value="k"
By correcting this I believe your issue will be resolved, you also noted a int to string conversion. depending on how/where this is happening this could also contribute to your headaches because this will never equate to true. '1231' === 1231
I'm creating a dynamic re-usable vue component that wraps a text input and includes the vuelidate validation stylings, etc.:
<template>
<div class="form-group" :class="{'form-group--error': validator.$error}">
<label>{{ label }}<span v-if="validator.$params.required">*</span></label>
<input type="text v-model="validator.$model" />
<div class="error" v-if="validator.$error && !validator.required">* This field is required</div>
</div>
<template>
<script>
export default {
name: "FormTextField",
props: ["validator", "label"]
}
</script>
(validator prop is $v from parent)
The problem I have is trying to show the <span>*</span> dynamically based on if the field is required. This currently works (v-if="validator.$params.required") as long as I only specify the required validator:
fieldName: {
required: required
}
Now, I need to instead declare my validation like this:
fieldName: {
required: requiredIf( ... )
}
The question is how to access the result of the requiredIf function? validator.$params.required will always be true since it's just checking if the param is there. And validator.required is the status of the validation, not the result of the requiredIf call to see whether it SHOULD be required or not.
Any suggestions on how I can show the required star dynamically based on vuelidate state?
Instead of validator.$params.required, check validator.required, which is only defined when there's a required or requiredIf validator rule applied. The value of validator.required is true when the field is missing, or false otherwise.
When the field is optional (has no required/requiredIf rule), the validator.required property does not exist, so we can't use v-if="!validator.required". Instead, explicitly compare validator.require to false:
<label>{{ label }}<span v-if="validator.required === false">*</span></label>
<div class="error" v-if="validator.$error && validator.required === false">* This field is required</div>
demo
I'm looking for the VueJS best practice for synchronizing between the input element and the switch element in the following piece of code:
<div class="filter panel">
<div class="field_title">Device</div>
<el-switch v-model="switches.device_switch" name="device"></el-switch>
<b-form-input v-model="device" placeholder="Device"></b-form-input>
</div>
If the input field contains any text I would like to set the v-model="switches.device_switch" to true.
How can I achieve this?
Set a watcher for the device property bound to the input. In the watcher, you can set the value of switches.device_switch based on the length of the device string:
watch: {
device: function(value) {
this.switches.device_switch = value.length !== 0;
}
}
I am using Date Range Picker to select to dates now when I select the dates, I update the inputs with dates value respectively.
The inputs I have binded with v-model and created a function in watch attribute of component to observe the change in model.
But when the inputs are updated with the javascript function no change can be observed in the model but the value of my input fields are updated.
// My Input Fields
<input type="text" name="updateStartDate" v-model="updateDateRange.start">
<input type="text" name="updateEndDate" v-model="updateDateRange.end">
//My javascript Function
$('input[rel=dateRangePickerX]').daterangepicker({
'autoApply': true,
'drops': 'up',
'startDate': moment().add(90, 'days').calendar(),
'endDate': moment().add(97, 'days').calendar(),
locale: { cancelLabel: 'Clear' }
},
function (start, end, label) {
$('input[name="updateStartDate"]').val(start.format('MM/DD/YYYY'));
$('input[name="updateEndDate"]').val(end.format('MM/DD/YYYY'));
});
// My watch attribute in Component
watch : {
'updateDateRange.end' : function (val) {
console.log('In Watch Function');
console.log(this.dateRanges);
if(val != '' && this.updateDateRange.start != '' && this.updateDateRangeIndex != ''){
console.log(val);
console.log(this.updateDateRange.start);
console.log(this.updateDateRangeIndex);
this.dateRanges[this.updateDateRangeIndex] = this.updateDateRange;
this.updateDateRangeIndex = '';
this.updateDateRange.start = '';
this.updateDateRange.end = '';
console.log(this.dateRanges);
}
}
}
I don't like to mix jQuery and Vue because jQuery messes up the DOM. Even more, I find it completely unnecessary.
Simple only with native Vue you can do it like this:
<input type="text" name="updateStartDate" v-model="startDate" #input="onInput()">
<input type="text" name="updateStartDate" v-model="endDate" #input="onInput()">
methods: {
onInput(e): function () {
// this will be called on change of value
}
}
Further to set the value and update the DOM simply update startDate and/or endDate variables and DOM will update accordingly.
You need to work with your model and not fiddle with the bound DOM element. You have bound the elements to viewmodel items:
<input type="text" name="updateStartDate" v-model="updateDateRange.start">
<input type="text" name="updateEndDate" v-model="updateDateRange.end">
then you use jQuery to set the field values
$('input[name="updateStartDate"]').val(start.format('MM/DD/YYYY'));
$('input[name="updateEndDate"]').val(end.format('MM/DD/YYYY'));
but you should be setting the bound values instead:
updateDateRange.start = start.format('MM/DD/YYYY');
updateDateRange.end = end.format('MM/DD/YYYY');