Vee-Validate custom errror component with scopes - vuejs2

I wanted to create a custom component to use Vee-Validate scopes to display the error.
Currently for the forms with the scope i am doing in a following ways.
Submit Method:
methods: {
onSubmit(scope) {
console.log(this.$validator)
this.$validator.validateAll().then((result) => {
if (result) {
alert('Form Submitted!');
}
});
}
}
HTML
<label>Name</label>
<input v-model="form_fields.name" data-vv-as="Partner name" data-vv-name="PartnerName" v-validate="'required'" :class="{'input': true, 'is-danger': errors.has('form-partner.PartnerName') }" type="text" class="form-control">
<div v-show="errors.has('form-partner.PartnerName')" class="help is-danger text-red">{{ errors.first('form-partner.PartnerName') }}</div>
which means i have to repeat errors.has('form-partner.PartnerName') multiple times, all over the forms.
I wanted to simplified as below.
<error-form :status="errors" :css-class="'is-danger'" label="Company Name" field="name">
<b-form-input v-validate="'required'" class="form-control" v-model="form_fields.name" name="name" data-vv-as="Company Name"
type="text" />
</error-form>
Similar to the implementation from here! but this is not working with the scopes.
I wanted to have the validation done with scopes. I will pass the scopes to the error-form as a prop like shown below.
///scope here
<error-form :status="errors" :scope='form-registraion' :css-class="'is-danger'" label="Company Name" field="name">
So, how i can check on my error-form component with the scopes? scopes could be mandatory or required.

Related

Use Vue.js Prop to populate vForm data?

I am still fairly new to using Laravel and Vue.js and have been having some problems when trying to submit data to be used in a modal form.
overview.vue is displaying some information and triggering the modal component
My modal element:
<EditTeamModal :existing="existing_team"/>
In my template I am triggering the following function
#click="getExistingTeam(membership.team)"
Which triggers the following method:
getExistingTeam: function (team) {
this.existing_team = team;
this.$bvModal.show('edit_team');
},
EditTeamModal.vue
In my modal component I have several inputs like the one following:
<div class="form-group row">
<label for="name" class="col-md-4 col-form-label text-md-right">{{ $t('team.name') }} <span class="text-danger">*</span></label>
<div class="col-md-8">
<input type="text" v-model="form.name" :class="{ 'is-invalid': form.errors.has('name') }" class="form-control" id="name" name="name" required/>
<has-error :form="form" field="name" />
<small id="nameHelp" class="form-text text-muted">Unique name of your team (155 character limit).</small>
</div>
</div>
and am setting my props and vForm data as follows:
props: {
existing: {
type: Object,
required: true,
default: {}
}
},
// middleware: 'auth',
data () {
return {
form: new Form({
id: this.existing.id,
name: this.existing.name,
region: this.existing.region,
website: this.existing.website,
about: this.existing.about,
membership_password: "",
membership_password_confirmation: "",
avatar: null,
}),
}
},
However, my form inputs are always blank...
I can access this.exists.name directly and get the proper expected data output, however it will not seem to populate into my form fields?!
Is there a proper way to pull data from a vue property into vForm form data?
Was able to get the modal form data to update by adding the following to my EditTeamModal.vue
watch: {
existing: function(val) {
this.form.fill(this.existing);
}
},

VueJs v-Model Binding with Hidden Component not working

I am developing a SPA application in Vue. I have a wizard in the wizard I have a component for each step. All the components are adding at the start and their mounted and created method/event is executing when the application starts.
I am using the event bus & when I move to the next step of wizard I emit the event and catch the event on the respective step.
Note: Component is hidden at the start and when it shows it will not have the updated data or even data in input fields.
Code of the component of the 2nd step is
<template>
<section>
<div class="container">
<form class="form-horizontal">
<div class="row form-group">
<label class="col-sm-3 control-label" for="marshaCode">MARSHA Code:</label>
<div class="col-sm-4">
<input type="text" class="form-control field-ml-15" v-model="marshaCode" placeholder="Enter Marsha Code" readonly />
<input type="text" class="form-control field-ml-15":value="marshaCode" placeholder="Enter Marsha Code" readonly />
<p>{{marshaCode}}</p>
</div>
</div>
</form>
</div>
</section>
</template>
<script>
import { EventBus } from "../../shared/eventbus.js";
export default {
data() {
return {
marshaCode:"On Load Code"
}
},
mounted() {
EventBus.$on('showSurvey', () => {
this.marshaCode="On Show Code"
});
},
}
</script>
Now when this component will show the P tag will have "On Load Code" But in both the fields there will be no data.
How can I rebind, re-render or update the data?
Use vue to show/hide the component using v-if or v-show. It can't do it's job if another library is messing with the DOM.
<section v-if='showMyComponent'>
or
<div class="col-sm-4" v-if='showMyComponent'>
<input type="text" class="form-control field-ml-15" v-model="marshaCode" placeholder="Enter Marsha Code" readonly />
<input type="text" class="form-control field-ml-15":value="marshaCode" placeholder="Enter Marsha Code" readonly />
<p>{{marshaCode}}</p>
</div>
And set showMyComponent to a computed or data property. Then remove the logic to show/hide from your other library.
You can simply add this.marshaCode="On Show Code" when mounted.
mounted() {
this.marshaCode="On Show Code"
console.log(EventBus)
EventBus.$on('showSurvey', () => {
this.marshaCode="On Show Code"
});
}
An example: https://codesandbox.io/embed/vue-template-8l2lg.

Vue.js and Vee Validate - How to update error message with error from an API

I am trying to set the error message from the vee-validate to one from an API.
<div class="col-md-12">
<label for="company-contact-name" class="label-input">Company Contact Name</label>
<input v-validate="validations.user.name" v-model="data.user.name" id="company-contact-name" class="form-control" type="text" name="name" placeholder="Enter contact name" />
<div id="name-error" class="msg-error text-danger">{{ errors.first('name') }}</div>
</div>
<div class="col-md-12">
<label for="email" class="label-input">E-mail address</label>
<input v-validate="validations.user.email" v-model="data.user.email" id="email" class="form-control" type="email" name="email" placeholder="Enter e-mail" />
<div id="email-error" class="msg-error text-danger">{{ errors.first('email') }}</div>
</div>
So, If the API returns an email error, I would like to edit the above "errors.first('email')" to the API error. Then, when the user starts to correct the field, the Vee Validate would show its configured errors.
This is an example of a possible array of errors:
[
{id: "name", title: "Name is invalid. It should have only letters"},
{id: "name", title: "Name is too short. It should have more than three characters"},
{id: "email", title: "Email has already been taken"}
]
What can be done to handle the API error messages?
Thanks for your time and attention.
Perhaps something like this - create a new validator which checks whether the API has returned an error message and if yes - returns that error message. Then use this new validator as a first validator for your field, but also add the built-in validator for email addresses.
<input
v-validate="api_email|email"
v-model="user.email"
id="email"
class="form-control"
type="email"
name="email"
placeholder="Enter e-mail" />
<script>
import { Validator } from 'vee-validate';
export default
{
data()
{
api_error: '',
user:
{
email: ''
}
},
mounted()
{
Validator.extend('api_email',
{
getMessage: this.emailError,
validate: this.validateEmail
});
},
methods:
{
validateEmail(value, args)
{
return !this.api_error;
},
emailError(field, args)
{
return this.api_error;
}
}
}
</script>
UPDATE
If you want to support an array of errors then perhaps you can do it like this
<div id="email-error" class="msg-error text-danger" v-for="err in [errors.first('email')].concat(array_with_api_errors.map(item => item.title))">{{ err }}</div>

v-on:model="form.email" expects a function value, got undefined

Vue.js 2 - I am trying to bind form inputs but I always get the erro message ( on all inputs ..)
v-on:model="form.email" expects a function value, got undefined
<form id="registrationForm">
<div class="form-group">
<input type="email" name="email" id="email" #model="form.email" placeholder="enter your email address">
</div>
<button #click="sendRegistration" type="submit" class="btn btn-primary btn-gradient submit">SEND</button>
</form>
and the script
data: function() {
return {
form: {
...
email: '',
...
}
}
},
methods: {
sendRegistration: function() {
console.log('sending form')
return false
}
},
You're getting some things mixed up. Attributes starting with v-on:, often abbreviated as #, are used to register event listeners on elements. #click="sendRegistration" will for example register the sendRegistration method defined on your Vue instance as a handler for that element's click event.
What you're trying to accomplish has nothing to do with event handling. The attribute you need is called v-model and binds an <input>'s value to a value saved on your Vue instance.
<input type="email" name="email" id="email" #model="form.email">
should be
<input type="email" name="email" id="email" v-model="form.email">

Vue Validator only after change / blur / submit

I'm using Vue for the first time, with Vue Validator. Here is an example of my code:
<label for="first_name">First name:
<span v-if="$validation1.first_name.required" class="invalid">Enter your first name.</span>
<input id="first_name" placeholder="e.g. Christopher" class="" v-validate:first_name="['required']" v-model="first_name" name="first_name" type="text">
</label>
The only issue at the moment is that when I land on the page with my form, the whole thing is covered in errors. Is there a way I can suppress the errors and only show them on input blur / form submit?
Argh, the Google-able word isn't about blur, or on submit – its about timing and initial:
http://vuejs.github.io/vue-validator/en/timing.html
<input id="first_name" initial="off" placeholder="e.g. Christopher" class="" v-validate:first_name="['required']" v-model="first_name" name="first_name" type="text">
you need to add .dirty or .touched to your validation
<label for="first_name">First name:
<span v-if="$validation1.first_name.required && $validation1.first_name.touched" class="invalid">Enter your first name.</span>
<input id="first_name" placeholder="e.g. Christopher" class="" v-validate:first_name="['required']" v-model="first_name" name="first_name" type="text">
</label>
I was dealing with a similar problem. I had to have an initialized variable for the input name: "" but I also wanted to have a required attribute in element.
So I add required when the event onblur occurs.
<input name="name" type="number" v-model="name" #blur="addRequired" />
const app = Vue.createApp({
data() {
return {
name: ""
}
},
methods:{
addRequired: function(event){
event.target.setAttribute("required", true);
}
}
});