vee-validate: Required only if a condition is met - validation

I'm using Vuejs2 and vee-validate for form validation. It's a great package, however I'm struggling to implement a conditional required field.
When a particular radio option is selected, I want two select fields to be required. And when that radio is not selected, I want the two select fields to be optional.
I've tried using the attach and detach methods. I can successfully detach the validation. And I can see when I attach a field it appears in the fields object. But it's not picked up by the validator.
Here is my code:
<template>
<form class="ui form" role="form" method="POST" action="/activate" v-on:submit.prevent="onSubmit" :class="{ 'error': errors.any() }">
<div class="ui segment">
<h4 class="ui header">Basic Company Information</h4>
<div class="ui message">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
<div class="field" :class="{ 'error': errors.has('name') }">
<div class="ui labeled input">
<label class="ui label" for="name">
Company
</label>
<input id="name" type="text" name="name" v-validate="'required'" v-model="name">
</div>
</div>
<div class="ui error message" v-show="errors.has('name')">
<p>{{ errors.first('name') }}</p>
</div>
<div class="grouped fields" :class="{ 'error': errors.has('organisation_type_id') }">
<label for="organisation_type_id">Organisation type</label>
<div class="field">
<div class="ui radio checkbox">
<input class="hidden" type="radio" name="organisation_type_id" value="1" data-vv-as="organisation type" v-validate="'required'" v-model="organisation_type">
<label>Buyer</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox">
<input class="hidden" type="radio" name="organisation_type_id" value="2" checked>
<label>Seller</label>
</div>
</div>
</div>
<div class="ui error message" v-show="errors.has('organisation_type_id')">
<p>{{ errors.first('organisation_type_id') }}</p>
</div>
<div v-show="organisation_type == '2'">
<div class="field" :class="{ 'error': errors.has('countries[]') }">
<label for="countries">Countries</label>
<select class="ui fluid search dropdown" id="countries" name="countries[]" multiple data-vv-as="countries" v-validate="'required'">
<option v-for="country in countries" :value="country.value">{{ country.text }}</option>
</select>
</div>
<div class="ui error message" v-show="errors.has('countries[]')">
<p>{{ errors.first('countries[]') }}</p>
</div>
<div class="ui message field-description">
<p>Select all the countries you export to.</p>
</div>
<div class="field" :class="{ 'error': errors.has('ciphers[]') }">
<label for="ciphers">Ciphers</label>
<select class="ui fluid search dropdown" id="ciphers" name="ciphers[]" multiple data-vv-as="ciphers" v-validate="'required'">
<option v-for="cipher in ciphers" :value="cipher.value">{{ cipher.text }}</option>
</select>
</div>
<div class="ui error message" v-show="errors.has('ciphers[]')">
<p>{{ errors.first('ciphers[]') }}</p>
</div>
<div class="ui message field-description">
<p>Select all the ciphers you support.</p>
</div>
</div> <!-- End organisation_type_id -->
<button class="ui fluid green button" type="submit">Continue</button>
</div> <!-- .ui.segment -->
</form>
</template>
<script>
export default {
props: ['countriesJson', 'ciphersJson'],
data() {
return {
name: null,
organisation_type: '2',
countries: [],
ciphers: [],
}
},
watch: {
organisation_type: function(value) {
var vm = this
if (value == '2') {
vm.$validator.attach('countries[]', 'required');
const select = document.getElementById('countries');
select.addEventListener('change', function() {
vm.$validator.validate('required', this.value);
});
vm.$validator.attach('ciphers[]', 'required');
const select = document.getElementById('ciphers');
select.addEventListener('change', function() {
vm.$validator.validate('required', this.value);
});
} else {
vm.$validator.detach('countries[]')
vm.$validator.detach('ciphers[]')
}
},
},
mounted() {
this.countries = JSON.parse(this.countriesJson)
this.ciphers = JSON.parse(this.ciphersJson)
},
methods: {
onSubmit: function(e) {
this.$validator.validateAll().then(success => {
e.target.submit()
}).catch(() => {
return
})
}
}
}
</script>

May be you mean something like this?
<input id="name"
type="text"
name="name"
v-validate="{ required: this.isRequired }"
v-model="name">
Where "isRequired" is computed field, which depend from condition

<input id="name"
type="text"
name="name"
v-validate=" isRequired ? 'required' : '' "
v-model="name">
In my case it worked by giving above condition.. Also it is helpful in case of multiple validation rules... e.g. 'required|integer|between:18,99'..
Adding {} will break the expression

you can simply use
v-validate="`required_if:${condition}`"

Related

How to fetch data from the database as a select option to the dropdown using API in laravel 9 with vue js 3

I have fields to submit to insert into the database. The account field has to select from options by Dropdown. The options should be fetched from the accounts table in the database and I have used API for that. I have coded and it can not see the accounts. Please instruct me to fix it.
the input types as follows.
<div class="modal-body">
<div class="form-row" v-show="!deleteMode">
<div class="form-group col-md-6">
<label for="exampleInputBorderWidth2">Funds From</label>
<select class='form-control' v-model='accountData.selectAccount'>
<option value='0' >Select Account</option>
<option v-for='data in selectAccounts' :value='data.id'>{{ data.name }}</option>
</select>
<span class="text-danger" v-show="accountError.selectAccount">Fund From required </span>
</div>
</div>
<div class="form-row" v-show="!deleteMode">
<div class="form-group col-md-6">
<label for="exampleInputBorderWidth2">Account Name</label>
<input type="text" class="form-control form-control-border border-width-2 text-danger text-lg" id="name" placeholder="Account Name" v-model="accountData.name" required>
<span class="text-danger" v-show="accountError.name">Name is required </span>
</div>
<div class="form-group col-md-6">
<label for="exampleInputBorderWidth2">Account Description</label>
<input type="text" class="form-control form-control-border border-width-2 text-primary text-lg" id="description" placeholder="Account Description" v-model="accountData.description">
<span class="text-danger" v-show="accountError.description">Description is required</span>
</div>
</div>
</div>
script as follows
data() {
return {
editMode: false,
deleteMode:false,
accountData:{
id: '',
name: '',
description: '',
status: '',
selectAccount: 0,
selectAccounts:[]
},
get Method
getSelectAccounts(){
axios.get("/api/allAccForSelect").then(response => {
this.selectAccounts = response.data
}).bind(this);
},
getDepAcc(){
axios.get("/api/depositAccount/depositAccountIndex").then(response => {
this.depAccs = response.data
}).catch(errors =>{
console.log(errors)
});
},
router API
Route::get('/allAccForSelect', [AccountController::class, 'allAccForSelect']);
Controller
public function allAccForSelect(Request $request)
{
$userId = Auth::id();
return response()->json(Account::where('user', $userId)->where('status', 1)->get());
}

Programatically trigger form validation with JQuery Validator don't work

According to the docs of jQuery Validator doing this should programatically trigger form validation.
var validator = $( "#myform" ).validate();
validator.form();
But in my code it does nothing, why? I have a submit button on my form that is working fine, but validator.form() doesn't work at all. I've updated the post with my HTML form as well as the javascript code.
This is my form
<form class="kt-form kt-form--label-right" id="frm_sok" action="ajax/artikkel.php?a=sok_artikler" method="post">
<div class="kt-portlet__body">
<div class="kt-blog-post">
<div class="form-group ">
<div class="col-12">
<input class="form-control" type="search" value="{{ sok }}" id="searchinput" name="searchinput">
</div>
</div>
<div class="row">
<div class="col-4">
<label>Ikke søk i :</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="1" id="skjulnyheter" name="skjulnyheter">
<label class="form-check-label" for="skjulnyheter">Nyheter</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="1" id="skjulforum" name="skjulforum">
<label class="form-check-label" for="skjulforum">Forum</label>
</div>
</div>
<div class="col-4">
<label for="sorter">Sorter:</label><br />
<select class="form-control" name="sorter" id="sorter">
<option value="a.opp_dato DESC">Nyeste</option>
<option value="score">Beste treff</option>
<option value="a.opp_dato ASC">Eldste</option>
</select>
</div>
</div>
</div>
</div>
<div class="kt-portlet__foot">
<div class="kt-form__actions">
<input type="submit" class="btn btn-primary sokknapp" value="Søk" />
</div>
</div>
</form>
Here is my Javascript:
$( window ).on( 'load', function()
{
var validator = $("#frm_sok").validate(
{
rules:
{
searchinput:
{
required: true
}
},
messages:
{
searchinput :
{
required : 'Du må neste søke etter noe. Noe som helst. Ett eller annet.'
}
},
invalidHandler: function(event, validator)
{
$('.error').css( "display", "inline-block !important");
},
submitHandler: function(form)
{
preload_kamp();
$(form).ajaxSubmit(
{
success: function(data)
{
$( "#sokcontent" ).html(data);
}
});
}
});
validator.form();
});

Why is my *ngIf condition not recognizing the error and displaying the message when the condition is met?

I have a custom validator that I am applying to an input field. My ngIf condition should display an error message if the form value has an error specific to the custom validator. It does not display the message, I cannot figure out why.
In my TS file:
export class ParentFinancialComponent implements OnInit {
// Set selected section value on load time.
selectedSectionGroup = {
sectionOne: false,
sectionTwo: true,
sectionThree: true,
sectionFour: true,
sectionFive: true,
sectionSix: true
};
public financialSectionTwo: FormGroup;
ngOnInit() {
this.initForm();
}
initForm() {
this.financialSectionTwo = this.formBuilder.group({
parents2017AdjustedGrossIncome: ['', [CustomValidators.onlyNumbers]],
parents2017IncomeTaxAmount: ['', [CustomValidators.onlyNumbers]],
parents2017TaxExemption: ['', [CustomValidators.onlyNumbers]]
});
get sectionTwo() { return this.financialSectionTwo.controls; }
}
In my HTML:
<div [hidden]="selectedSectionGroup.sectionTwo" class="tab-pane
fade show active"
id="{{financialSectionEnum.SECTION_TWO}}" role="tabpanel">
<form [formGroup]="financialSectionTwo">
<p class="section-header">Section II</p>
<div class="form-group row"
[hidden]="sectionOne.parentsIrsStatus.value === '3'">
<p class="col-lg-9"><b class="q-num">89)</b><span
[hidden]="sectionOne.parentsIrsStatus.value !== '1'"
class="form-required">*</span>Income for 2017?<i
class="fa fa-info-circle" aria-hidden="true"></i></p>
<div class="col-lg-3">
<label class="sr-only">Adjusted gross
income</label>
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">$</div>
</div>
<input
maxlength="9"
formControlName="parents2017AdjustedGrossIncome"
id="parents2017AdjustedGrossIncome"
type="text"
class="form-control col-3 col-lg-12"
data-hint="yes"
>
<div class="input-group-append">
<div class="input-group-text">.00</div>
</div>
<div
*ngIf="sectionTwo.parents2017AdjustedGrossIncome.touched &&
sectionTwo.parents2017AdjustedGrossIncome.errors.onlyNumbers"
class="alert text-danger m-0 p-0 col-md-12"
>
Enter an amount
</div>
</div>
</div>
If i enter an alphabet, I should get the error message "Enter an amount". I have other inputs that depend on multiple custom validators, so checking to see if the input field is just "invalid" will help me. I need the message to display only if a specific custom validator is triggered.
You didn't include the implementation for your custom validator: CustomValidators.onlyNumbers so can't say what is wrong with the logic... however, the following implementation could get what you wanted !!
validator:
CustomValidatorsOnlyNumbers(control: AbstractControl) {
var pattern = /^\d+$/;
if ( pattern.test(control.value) == true ){ return true;} else {
return { onlyNumbers: true };
}
}
relevant HTML:
<div class="tab-pane fade show active"
role="tabpanel">
<form [formGroup]="financialSectionTwo">
<p class="section-header">Section II</p>
<div class="form-group row" >
<p class="col-lg-9"><b class="q-num">89)</b><span
class="form-required">*</span>Income for 2017?<i
class="fa fa-info-circle" aria-hidden="true"></i></p>
<div class="col-lg-3">
<label class="sr-only">Adjusted gross
income</label>
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">$</div>
</div>
<input
maxlength="9"
formControlName="parents2017AdjustedGrossIncome"
type="text"
class="form-control col-3 col-lg-12"
data-hint="yes"
>
<div class="input-group-append">
<div class="input-group-text">.00</div>
</div>
<div
*ngIf="financialSectionTwo.get('parents2017AdjustedGrossIncome').touched && financialSectionTwo.get('parents2017AdjustedGrossIncome').hasError('onlyNumbers')"
class="alert text-danger m-0 p-0 col-md-12"
>
Enter an amount
</div>
</div>
</div>
</div>
</form>
</div>
complete working stackblitz here

close parent modal and open child modal on axios success response with laravel vue js

User have to register through two steps. both steps have modal to fill details. for that i have two component ComponentA for first modal and componentB for second modal. Iwant to close first modal on axios success response and open second modal for second registration step.
<template>
<!--sction user-signup 1-->
<div class="signup">
<div class="modal" id="user-signup-1">
<div class="modal-dialog">
<div class="modal-content">
<button type="button" class="close" data-dismiss="modal">×</button>
<!-- Modal body -->
<div class="modal-body text-center" style="background:url(images/user-signup-bg.jpg) no-repeat left top; ">
<h2>SIGN UP</h2>
<h5 class="setp-tag">Step 1 of 2</h5>
<h6>Registered users have access to all MoneyBoy features. This is not a Moneyboy Profile.<br>
If you’d like to create a Moneyboy Profile please click here.</h6>
<form class="user-signup-form" action="./api/user/signup" method="POSt" #submit.prevent="addUser()">
<div class="form-group">
<label>Username</label>
<input type="text" name="username" v-model="username" placeholder="mohamed-ali" class="span3 form-control">
<span v-if="hidespan">5 - 20 characters. Letters A-Z and numbers 0-9 only. No spaces.
E.g. MikeMuscleNYC.</span>
<span v-if="errorinusername"> {{ errorinusername }}</span>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" name="email" v-model="email" placeholder="mohamed-ali#gmail.com" class="span3 form-control">
<span v-if="errorinemail"> {{ errorinemail }}</span>
</div>
<div class="form-group">
<label>Create a password</label>
<input type="password" name="password" v-model="password" placeholder="**********" class="span3 form-control">
<span v-if="errorinusername"> {{ errorinpassword}}</span>
</div>
<div class="form-group turms">
<input name="" type="checkbox" value="1" v-model="checked" id="terms"><label for="terms">I am over 18 and agree to the
Terms & Conditions</label>
<!--<label><input type="checkbox" name="terms">I am over 18 and agree to the Terms & Conditions.</label>-->
<input type="submit" :disabled="!checked" value="SIGN UP NOW" class="btn btn-primary w-100">
</div>
<div class="form-group">
<p>If you’d like to create a Moneyboy Profile click here.</p>
</div>
<div class="clearfix"></div>
</form>
</div>
</div>
</div>
</div>
<usersignup2component #recordadded="openusersignup2modal()"></usersignup2component>
</div>
<!--sction user-signup 1-->
</template>
<!--sript -->
<script>
Vue.component('usersignup2component', require('./UserSignup2Component.vue').default);
export default {
data(){
return {
username: '',
email:'',
password:'',
checked: false,
errorinusername: '',
errorinemail: '',
errorinpassword: '',
hidespan: true,
}
},
methods:{
addUser(){
axios.post('./api/user/signup', {
username:this.username,
email:this.email,
password:this.password
})
.then((response) =>{
this.$emit('recordadded');
})
.catch((error) => {
console.log(error.response);
this.hidespan = false;
this.errorinusername = error.response.data.errors.username;
this.errorinemail = error.response.data.errors.email;
this.errorinpassword = error.response.data.errors.password;
});
},
openusersignup2modal(){
console.log('okkkkkkkkkkkkkk');
}
},
mounted() {
console.log('UserSignUp1Component mounted.')
}
}
</script>
What I am doing wrong. I tried to console.log() on openusersignup2modal method to see, if it this function ever called or not. Found no activity on openusersignup2modal()

Laravel Vue.js API: axios' PUT method doesn't send any data to controller

I'm trying to update some data in Model using API in Laravel and Vue.js
but I can't do this because axios doesn't send any data to server, I'm checking the data right before sending and they exist (I use FormData.append to add all fields)
I check data before sending using the code:
for(var pair of formData.entries()) {
console.log(pair[0]+ ': '+ pair[1]);
}
and I get this result:
You can check the appropriate code:
[function for updating]
updateStartup() {
let formData = new FormData();
formData.append('startup_logo', this.update_startup.startup_logo);
formData.append('country_id', this.update_startup.country_id);
formData.append('category_id', this.update_startup.category_id);
formData.append('startup_name', this.update_startup.startup_name);
formData.append('startup_url', this.update_startup.startup_url);
formData.append('startup_bg_color', this.update_startup.startup_bg_color);
formData.append('startup_description', this.update_startup.startup_description);
formData.append('startup_public', this.update_startup.startup_public);
axios.put('/api/startup/' + this.update_startup.id, formData, { headers: {
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW',
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error.response);
});
}
[controller method where I should receive data]:
public function update(Request $request, $id) {
return $request; // just for checking if I get data
...
}
[HTML with vue.js where I use object which I send in updateStartup function]:
<!-- Modal edit -->
<div class="modal fade editStartUp" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<img src="/admin/images/modal-cross.png" alt="Close">
</button>
</div>
<div class="modal-body">
<form method="POST" enctype="multipart/form-data" #submit.prevent="updateStartup">
<h4 class="sel-c-t">Select category</h4>
<div class="submit-fields-wr">
<select name="category" v-model="update_startup.category_id" class="selectpicker select-small" data-live-search="true" #change="updateCategoryDetails()">
<option v-for="category in categories" :value="category.id" :selected="category.id == update_startup.category_id ? 'selected' : ''" >{{ category.name }}</option>
</select>
<select v-if="update_startup.is_admin" name="country" v-model="update_startup.country_id" class="selectpicker select-small" data-live-search="true" #change="updateCountryDetails()">
<option v-for="country in countries" :value="country.id" :selected="country.id == update_startup.country_id ? 'selected' : '' ">{{country.name }}</option>
</select>
</div>
<div class="submit-fields-wr">
<input type="text" placeholder="Startup name" v-model="update_startup.startup_name">
<input type="url" v-model="update_startup.startup_url" placeholder="URL">
</div>
<textarea v-model="update_startup.startup_description" name="startup_description" placeholder="Describe your startup in a sentence.">
</textarea>
<div v-if="!update_startup.is_admin">
<h4 class="sel-c-t bold">Contact details:</h4>
<div class="submit-fields-wr">
<select name="country" v-model="update_startup.country_id" class="selectpicker select-small" data-live-search="true" #change="updateCountryDetails()">
<option v-for="country in countries" :value="country.id" :selected="country.id == update_startup.country_id ? 'selected' : '' ">{{country.name }}</option>
</select>
<input type="text" placeholder="Your Name" v-model="update_startup.contact_name">
</div>
<div class="submit-fields-wr">
<input type="text" v-model="update_startup.contact_phone" placeholder="Your phone number">
<input type="email" v-model="update_startup.contact_email" placeholder="Your email address">
</div>
</div>
<p class="upl-txt">Company’s logo.<span>(upload as a png file, less than 3mb)</span></p>
<div class="file-upload">
<div class="logo-preview-wr">
<div class="img-logo-preview">
<img :src="update_startup.startup_logo" alt="logo preview" id="img_preview">
</div>
</div>
<label for="upload" class="file-upload_label">Browse</label>
<input id="upload" #change="onFileUpdated" class="file-upload_input" type="file" name="file-upload">
</div>
<div class="preview-divider"></div>
<h4 class="sel-c-t bold">Preview:</h4>
<div class="preview-wrapper-row">
<a href="#" class="start-up-wr">
<div class="start-up-part-1 edit">
<div class="flag-cat-wr">
<div class="flag-wr">
<img :src="update_startup.country_flag" :alt="update_startup.country_name">
</div>
<div class="category-wr">
{{ update_startup.category_name }}
</div>
</div>
<img :src="update_startup.startup_logo" :alt="update_startup.startup_name" class="start-up-logo">
</div>
<div class="start-up-part-2">
<h4 class="startup-name">{{ update_startup.startup_name }}</h4>
<p class="startup-description">
{{ update_startup.startup_description }}
</p>
</div>
</a>
<div class="color-picker-btns-wr">
<div>
<input type="text" class="color_picker" v-model="update_startup.startup_bg_color">
<button class="colo_picker_btn">Background Color</button>
</div>
<div class="modal-bottom-btns">
<div class="btn-deactivate-active">
<button type="submit" class="btn-deactivate" #click="deactivateExistingStartup()">Deactivate</button>
<button type="submit" class="btn-activate" #click="activateExistingStartup()">Activate</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Modal edit -->
[Additional info - also when I open modal(where I have form for updating) I change form data accordingly to startup id]:
showUpdateStartup(startup) {
setTimeout(() => {
$('.selectpicker').selectpicker('refresh');
}, 50);
this.update_startup.id = startup.id;
this.update_startup.category_id = startup.category.id;
this.update_startup.category_name = startup.category.name;
this.update_startup.startup_name = startup.name;
this.update_startup.startup_description = startup.description;
this.update_startup.startup_url = startup.url;
this.update_startup.startup_logo = startup.logo;
this.update_startup.startup_bg_color = startup.startup_bg_color;
this.update_startup.contact_id = startup.contact.id;
this.update_startup.contact_name = startup.contact.name;
this.update_startup.contact_phone = startup.contact.phone;
this.update_startup.contact_email = startup.contact.email;
this.update_startup.country_id = startup.contact.country.id;
this.update_startup.country_flag = startup.contact.country.flag;
this.update_startup.country_name = startup.contact.country.name;
this.update_startup.is_admin = startup.contact.is_admin;
this.update_startup.startup_public = startup.public;
},
Let me know if you have any additional questions
Thank you guys a lot for any help and ideas!
Try using formData.append('_method', 'PATCH') with axios.post method.
Return the input data instead of the Request object from your controller:
return $request->input();

Resources