Invalid form for default selected option in Vue - vue.js

I have the following form in VueJs 2
<form id="trial-form" action="post" class="trial">
<div class="form-field required selectbox">
<select name="region" id="region" label="region" v-validate="'required'" v-model="region" class="required selectbox region" aria-label="Region">
<option value="">{{ $t("region") }}</option>
<p-option v-for="regionOption in regionList" :key="regionOption.region" :value="regionOption.plane">{{$t(regionOption.region)}}</p-option>
</select>
<p-button size="lrg" align="left" type="submit" :disabled="isFormInvalid" #click.prevent="validateBeforeSubmit">{{ $t("trialSubmit") }}</p-button>
</div>
</form>
I am setting the v-model hardcoded and the code is as follows:
mounted () {
this.region = 'US'
}
This sets the US as selected in the select box. My validation function is as follows:
computed: {
isFormInvalid () {
return Object.keys(this.fields).some(key => this.fields[key].invalid)
}
}
Now even though the value in the select dropdown is shown as selected by default, the submit button is not activated. If I change the select options, then the button is activated and I am able to submit the form. As the select box is showing as selected by default, user should be able to submit without selecting it manually. What is wrong here ? Thanks in advance

To validate the field as soon as the page loads, You should use directive modifier .immediate
<select name="region" id="region" v-validate.immediate="'required'" v-model="region">
Or other workaround solution is just to check if v-model contains a value or not and returns boolean value by using a computed property and add a errors.any() along with this computed property for a more robust solution.
In Script :
computed: {
isFormInvalid () {
return !this.region;
}
}
In Template :
<p-button type="submit" :disabled="errors.any() || isFormInvalid" #click.prevent="validateBeforeSubmit">{{ $t("trialSubmit") }}</p-button>

Related

true / false in input (vuejs), probably without v-model

I have an array with many checkbox.
<li v-for='item in resultQuery' :key='item.id'>
<label class='custom-checkbox'>
<input type='checkbox' :value='item.id' v-model='checkBrands'>
<span #click='loadProducts(item.seoName)>{{ item.title }}</span>
</label>
</li>
I need to get true or false (depends on checkbox). How can I do this without affecting the v-model? (Use it to transfer an array of selected checkbox).
Needed to trigger a specific mutation
.then((response) => {
if(true) {
this.$store.commit(
'showFilteredList',
response.data.items
);
} else {
this.$store.commit(
'deleteCheckboxItems',
response.data.items
);
}
});
You can using #change on checkbox.
Example: https://codepen.io/koei5113/pen/ZEXLLgL
<input type='checkbox' :value='item.id' v-model='checkBrands' #change="changeEvent">
methods: {
...,
changeEvent($event) {
console.log($event.target.checked);
}
}
In this example you can see your v-model still working and you still can check checkbox status by the change event.
v-model ignore the :value in the input. You need to use :checked and #change
For example, and when you emit the change event use your function.
<input type="checkbox" :checked="value" #change="changeArrayNotValue" />

Binding getter array to checkbox group

I have a two page form so I am trying to mix submitting data to the server as well as making use of vuex. So on page one, I have a simple form which contains a group of checkboxes (removed layout and styling to reduce code)
<b-form #submit.stop.prevent="onSubmit">
<b-form-group>
<input v-model="$v.form.checkboxGroup.$model" type="checkbox" name="checkbox1" value="1">
<input v-model="$v.form.checkboxGroup.$model" type="checkbox" name="checkbox2" value="2">
<input v-model="$v.form.checkboxGroup.$model" type="checkbox" name="checkbox3" value="3">
</b-form-group>
<button class="btn try-btn" type="submit">Submit</button>
</b-form>
Essentially, when submitted, I send the form data to my repository so it can be saved on the backend. If this is successful, I call the following method
handleSubmitSuccess (response) {
if (response.data.action === 'next_step') {
this.$store.dispatch('createCheckboxData', this.$v.form.$model)
return
}
}
This method sets the checkbox data in my store and routes the user to the next page (removed this part). So all of this is fine, seems to work well.
So when on page two, I have a button that can take you back to page one. My idea is that if this happens, I use the previously checked data in the store to auto check the previously selected checkbox. As such, on page one I added a computed method
computed: {
checkboxData () {
return this.$store.getters.checkboxData
}
}
Now if I output checkboxData to the console, it seems to be an Observer object
[{…}, __ob__: Observer]
0:
checkboxData: Array(2)
0: "1"
1: "3"
length: 2
So the above shows that previously, the first and second checkboxes were checked.
My question is how can I now use this data to auto-check my checkboxes. I have seen some examples online, but they do not seem to work.
Thanks
The way you use Vue is a little different to me so you might have to change this but, basically, you can set your v-model to whatever array is set in the Vuex store and it will set those checkboxes to true:
new Vue({
el: "#app",
data: {
checkbox: [],
vuexData: ['1', '3']
},
mounted() {
this.checkbox = this.vuexData;
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="checkbox" type="checkbox" name="checkbox1" value="1">
<input v-model="checkbox" type="checkbox" name="checkbox2" value="2">
<input v-model="checkbox" type="checkbox" name="checkbox3" value="3">
{{ checkbox }}
</div>

Using vee-validate for validation of dropbox

Sorry for the very basic question
I'm trying to validate a form using vee-validate. text/email/number fields are not a problem. But I couldn't find a good documentation on validating dropdown/checkbox/radio fields.
What I want is "you have to select some option from the dropdown". For that i tried
<p class="help is-danger" v-show="standard===''">Select the standard student is studing in.</p>
where standard is the property which is binded with the help of v-model="standard". This is working as intended, but i want this message to be shown when dropdown is "touched". I'm not able to figure this out.
You can use the data-vv-validate-on attribute:
data-vv-validate-on="focus"
Then whenever the dropdown is opened the validator will fire, for instance.
I found a workaround for this,
<div class="select" :class="{'is-success': standard!='', 'is-danger': standard=='' && standardIsFocused}">
<select v-model="standard" #focus.once="standardToggle()">
...
</select>
</div>
<p class="help has-text-left is-danger" v-show="standard==='' && standardIsFocused">Selecting one of the option is required.</p>
in script tags
data () {
return {
standardIsFocused: false,
},
methods: {
standardToggle() {
this.standardIsFocused = !this.standardIsFocused
}
}

Aurelia repeater: model.bind is not working for radio buttons

I am creating a set of radio buttons in Aurelia with the code like this:
<div repeat.for="option of options">
<input type="radio" id="${option}_id" name="radio_options" model.bind="option" checked.bind="optionValue"/>
<label for="${option}_id" id="${option}_label">${option}</label>
</div>
However, doing it this way I discovered that model.bind is not working - the optionValue in corresponding class is not populated when radio button is checked. Similarly when some value is assigned to optionValue in the class, the appropriate radio button is not checked. I found this happening only with repeater. Options are numbers in my case. Could you please help me to find out what may be wrong here?
The first problem is that model.bind should be used when working with objects. Since you're working with a primitive type, you should use value.bind instead.
The second problem is that input values are always strings, so when setting an initial value, it must be a string. For example:
Html:
<template>
<div repeat.for="option of options">
<input type="radio" id="${option}_id" name="radio_options" value.bind="option" checked.bind="optionValue"/>
<label for="${option}_id" id="${option}_label">${option}</label>
</div>
<p>Selected Option: ${optionValue} </p>
</template>
JS:
export class App {
options = [ 1, 2, 3, 4 ]
optionValue = '3';
}
If you really want to use int in your view-model, you can create a ValueConverter to convert the value to int when passing it to/from the view. For instance:
export class AsIntValueConverter {
fromView(value) {
return Number.parseInt(value);
}
toView(value) {
return value.toString();
}
}
Usage:
<input type="radio" id="${option}_id" name="radio_options" value.bind="option" checked.bind="optionValue | asInt"/>
Running Example https://gist.run/?id=1465151dd5d1afdb7fc7556e17baec35

Angular2 how to clear the input value on submit without passing dom element

I've read that it is not good practice to pass the dom element so I come up with such view:
<div>
<input #message placeholder="message" (keyup.enter)="add(message.value)" />
<button (click)="add(message.value)">Add+</button>
<p>
the message is {{ message.value }}
</p>
</div>
As you can see I am passing the message.value to my add method
add(message: string) {
this.message = message;
console.log(this.message);
this.messengerService.add(this.message);
}
But how can I clear the so inside add method so input #message won't containg any text? I tried message = null; but it is does not work.
If you extend your response with (blur)= , you can reset the input field as follows:
<div>
<input #message placeholder="message (keyup.enter)="add(message.value)" (blur)="add(message.value); message.value='' " />
<button (click)="add(message.value)">Add+</button>
<p>
the message is {{ message.value }}
</p>
</div>
Note added: (blur)=add(message.value); message.value=''
you can use ngModel instead of #elem.value :
<div>
<input placeholder="message" [(ngModel)]="message" (keyup.enter)="add(message)"/>
<button (click)="add(message)">Add+</button>
<p>
the message is {{ message }}
</p>
</div>
and then clear the input value by adding
this.message = null;
in add function. This will work :
add(message: string) {
this.message = message;
console.log(this.message);
this.messengerService.add(this.message);
this.message = null;
}
your message.value attribute in view was not mapped to this.message in modal
Why to use extra Parameter when angular provides two way data binding in the form of [(ngModel)]. you can use ngModel to get notified both side on view as well as in the class/controller. no need to pass extra parameter along with method call. so you can use this simplified approach here
<div>
<input placeholder="message" [(ngModel)]="message" (keyup.enter)="add()"/>
<button (click)="add(); message = null">Add+</button>
<p>
the message is {{ message }}
</p>
</div>
message: string = null;
add() {
console.log(this.message);
// this.messengerService.add(this.message);
}
here is working demo for the same Working Plunker
The ngModel input property sets the element's value property and the ngModelChange output property listens for changes to the element's value. The details are specific to each kind of element and therefore the NgModel directive only works for elements, such as the input text box.