VeeValidate 3.x get specific classes from ValidationProvider by name - javascript

I'm using Vee Validte 3.x in my Nuxt JS/Vue project. I need to be able to get the classes from a particular Validation Provider element by it's name or some unique identifier and output the classes object somewhere else on my page.
I'm struggling to figure out how, and thought a ref would work but didn't.
Here's my code:
<!-- Data Source (Table) (Validation Workaround) -->
<validation-provider
tag="div"
name="data source"
:rules="{ required: { allowFalse: false } }"
v-slot="{ errors, classes }"
>
<CustomInput
class="hidden-spans"
:options="editor.sources"
v-model="mockedCheckboxes.source.isChecked" />
<span class="block text-xs text-red-500 mt-1">{{ errors[0] }}</span>mockedCheckboxes.source.classes = classes" />
</validation-provider>
I'd like to be able to do something like:
this.$validator('data source').classes
Somewhere in my Vue file so that I can use the classes from one input elsewhere, this isn't working though.

this.$validator was actually removed in favor of ValidationObserver: https://vee-validate.logaretm.com/v3/migration.html#migrating-from-2-x-to-3-0
So far, if you try to validate something that is not directly in the component you're working on, you should watch the flags of the validation (errors) and update the status on a Vuex store. Then access Vuex back to decide if the input is valid and proceed further.
There is no global validation to my knowledge.

Related

How to pass selected file from file upload button to slot props when using vue-csv-import?

So I'm making an app right now that's using a package called vue-csv-import and in the docs it tells me that I can define my custom element inside the vue-csv-input component it provides which exposes two slot props v-slot="{file, change}". I've been clawing my eyes out trying to find a way for my code to work. I tried doing it like this but it doesn't work. It somehow can't find my uploaded file in my custom file input but the component works when I'm not defining a custom input and just use the default input the package provides. The package documentation has no examples on how to do actually use the slot props for a custom file input so I can't rely on that.
MyComponent
<vue-csv-input v-slot="{file, change}">
<label for="finput" class="fancy-upload-btn">Upload CSV File</label>
<input #change="change" type="file" name="file" id="finput">
</vue-csv-input>
VueCsvInput from vue-csv-import
<template>
<slot :file="file" :change="change">
<input ref="csvRef" type="file" change="change" :name="name" v-bind="$attrs">
</slot>
</template>
What's inside the change function in VueCsvInput
const change = function () { let tmpFile = csvRef.value.files ? csvRef.value.files[0] : null;
if (validate(tmpFile)) { VueCsvImportData.file = tmpFile;
}
}
I've tried ddding ref="csvRef" to my custom file input but doesn't work either. It always ends up not getting the uploaded the file and the package documentation has no examples on using it with a custom file input, only that it provides the props to do so.
Your help would be highly appreciated. If you have an alternative package to recommend then that would be nice too.

Can't get Bootstrap-vue form validation working

I am using Vue CLI and Bootstrap and am having trouble with the form validation currently when the page loads all the input fields load as invalid. I can see why this is happening because the input fields are getting a class of is-invalid. I have fixed this by passing the state prop a value of null when it is false. It does not seem like the default behavior should be to run the validation when the page loads but maybe it is. I believe I have everything set up correctly as far as structure and proper classes I followed the bootstrap-vue docs.
My Code
<b-form
#submit.prevent="addReview"
name="review-form"
class="needs-validation"
novalidate
>
<div class="name">
<label class="sr-only" for="form-input-name">Name</label>
<b-input
id="form-input-name"
class="form-inputs mb-2 mr-sm-2 mb-sm-0"
v-model="name"
placeholder="Name"
required
:state="isEmpty(this.name) ? true : null" <---- My problem is here
></b-input>
...
</b-form>
My problem is I need 3 results from this ternary which obviously isn't possible. I need null on load to remove the error messages then false to display error on validation and true to display valid input. I have been struggling with this for days so any help with any aspect of this setup would be greatly appreciated if you want more code let me know. The submit button adds a class of was-validated which does display any error messages that are associated with empty inputs but doesn't validate the inputs.
Question
How do I validate inputs while still keeping form error messages hidden on load.
You aren't bound to just using a ternary statement in the :state prop - you can hook :state up to a computed property directly, which will achieve three things (this is similar to what is shown in the documentation):
We can have more than two conditions, breaking out of the limitations of the ternary statement.
The computed property will analyze user input on the fly, ensuring real-time validation of the form input.
Our template code will be cleaner and more readable (important).
I'm working loosely off of your example, but something like the following should solve your issue:
<template>
<div id="app">
<img width="25%" src="./assets/logo.png" style="margin-bottom: 15px;">
<b-form>
<div class="name">
<label class="sr-only" for="form-input- name">Name</label>
<b-input v-model="name" id="form-input-name" :state="isNameStateValid"></b-input>
</div>
</b-form>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
name: ""
};
},
methods: {
isValid() {
return this.name.length > 3 ? true : false; //your validation criteria goes here
}
},
computed: {
isNameStateValid() {
if (this.name) {
return this.isValid(this.name);
}
return null;
}
}
};
</script>
In the above, you would have a method that would check for your specific validation criteria (isValid, isEmpty, etc.).
Our new computed property, isNameStateEmpty, will use that method's return value, returning false for a validation failure (triggering BootstrapVue's failed validation state), true for a validation pass, or null in the event that this.name does not have a current value (examples being a fresh page load, or a user clearing the input field, making it blank).
See a working Codesandbox of this behavior here.
Because the input's v-model (v-bind:value and #change) is set to our "name" data property, every character change within the input field will reactively update our data property (this.name).
Because our isNameStateValid computed property has a dependency of this.name, it will reevaluate on every change of the this.name data property - ensuring real-time validation using BootstrapVue's validation state.
Hopefully that helps.

Polymer v1.0 input validation on button click

Noob at polymer here, so please bear with me.
I'm trying to learn how to create a form, one that requires the user to input text into a textbox, before hitting "Submit". Should the user hit "Submit" without anything in the textbox, the textbox is highlighted red, and displays an error message, etc.
Here's my code (no validation yet) so far:
<dom-module id="accountability-ticket">
<template>
<paper-dialog with-backdrop entry-animation="scale-up-animation" exit-animation="fade-out-animation" id="diagTicket">
<h2>I Own It Ticket</h2>
<div>
<paper-input-container id="gcashDeco" required error="GCash Ref. Required">
<input id="gcashText" is="iron-input">
</paper-input-container>
<div class="ctrlButtons flex">
<paper-button dialog-dismiss>Cancel</paper-button>
<paper-button on-click="confirmClick">Submit</paper-button>
</div>
</div>
</paper-dialog>
</template>
</dom-module>
<script>
Polymer({
is: "accountability-ticket",
confirmClick: function(event){
console.log(event);
var gCashDeco = document.getElementById('gcashDeco');
var gCashText = document.getElementById('gcashText');
}
});
</script>
I've been reading the Polymer documentation, and so far came up with two things:
<paper-input> doesn't validate, per se, according to v0.5 - It must be wrapped in <paper-input-decorator> first.
Version 1.0 is even less clear than that, with <paper-input-container> instead of <paper-input-decorator>, and mixed tags in the demo pages.
Given that I want to stick with the latest version (v1.0), what do I need to add to my code to get it to check if the textbox is empty, and display an error message if it is?
Thanks.
Yep, the Polymer docu is somewhat confusing, but as a general rule of thumb: always have a look at the behaviours the element is equiped with.
So, paper-input (in 1.0) comes with PaperInputBehavior and this implies that you can simply write the following:
<paper-input label="Input label" required error-message="Field required!"></paper-input>
<paper-input label="Input label" minlength="4" maxlength="10" auto-validate></paper-input>
<paper-input label="Input label" pattern="MY_REGEX" auto-validate></paper-input>
<paper-input label="Input label" validator="myvalidator"></paper-input>
auto-validate makes the input – of course – validate as it is being typed into. myvalidator must be an element implementing the IronValidatorBehavior and inserted somewhere on the page. If you don't want the fields to be auto-validating or wanna do it yourself, call validate() on that field or set the invalid-flag and the error message will be shown. You can even adjust the message programmatically.
While the validator seems to be useful, I've found it to be simple enough to test the inputs directly. This will do what you need:
...
<div>
<paper-input-container id="gcashDeco">
<paper-input-error>Field is empty</paper-input-error>
<input id="gcashText" is="iron-input" value="{{gcashInput::input}}">
</paper-input-container>
<div class="ctrlButtons flex">
<paper-button dialog-dismiss>Cancel</paper-button>
<paper-button on-tap="confirmClick">Submit</paper-button>
</div>
</div>
...
...
Polymer({
is: "accountability-ticket",
confirmClick: function() {
if (this.gcashInput == null)
{
//show error
this.$.gcashDeco.invalid = true;
}
}
This paper-input-error element is referenced by the id of whatever paper-input-container it is inside of. Setting it's invalid property to true shows the error, and false hides it.
<paper-input-error>Field is empty</paper-input-error>
This next snippet binds the field's input value to a variable this.gcashInput which you can access inside confirmClick or any other method.
{{gcashInput::input}}
As a final note, getting id's of elements inside of your Polymer element is done like this:
this.$.gcashDeco
Not the way you would with vanilla Javascript:
document.getElementById('gcashDeco');
The latter, vanilla JS way, would search the main DOM, not the Shadow DOM where your element resides. So, use document.getElementById() if you need to search the DOM, and use this.$.elemendId if you need to search your element for an id.

How to use the same form for updating/inserting records using quickForm?

I have this Meteor template:
<template name="personalDetailsForm">
{{> quickForm collection="PersonalDetails" id="personalDetailsForm" type="insert"}}
{{> quickForm collection="PersonalDetails" doc=editingDoc id="personalDetailsForm" type="update"}}
</template>
The forms are displayed as I expect, however I just want one form. A blank form for when there is no data which does an insert when the form is submitted. Then when the form is reloaded the data previously submitted is shown on the form. If the form is then submitted again any data that has changed will be updated.
Currently the insert form is displaying and underneath it the update form is displaying, with the data that has been previously inserted. Trying to update the data on the second form doesn't work, instead it inserts a new record. This I imagine could be because the form ids are the same.
Ideally I would like to do something like this:
<body>
{{#if PersonalDetails}}
{{> personalDetailsFormUpdate}}
{{ else }}
{{> personalDetailsFormInsert}}
{{/if}}
</body>
<template name="personalDetailsFormInsert">
{{> quickForm collection="PersonalDetails" id="personalDetailsFormInsert" type="insert"}}
</template>
<template name="personalDetailsFormUpdate">
{{> quickForm collection="PersonalDetails" doc=editingDoc id="personalDetailsFormUpdate" type="update"}}
</template>
I think this part of the documentation is what I'm looking for:
Can I reuse the same quickForm or autoForm for both inserts and updates?
Yes. Your code that flips between states should do the following in this order:
Change the type attribute's value to "insert" or "update" as appropriate, probably by updating a reactive variable.
Change the doc attribute's value to the correct document for an update or to null (or a document containing default values) for an insert, probably by updating a reactive variable.
Call AutoForm.resetForm(formId). This will clear any existing validation errors for the form.
Can anyone provide an example of this?
The question was asked some time ago, but I had the same issue and just solved it.
It is quite easy:
Get the context data as usual. E.g. with iron-router, build a route like:
Router.route('Options', {
path: 'options',
data: function() {
var options = Options.findOne({owner: Meteor.userId()});
return options;
}
});
Build a new helper, that checks if the context data (this in the helper) is empty or not (example is for a global helper that works in every template):
UI.registerHelper("formType", function(){
if(_.isEmpty(this)) {
return 'insert'
} else {
return 'update';
}
});
Setup the template with the new helper:
<template name="Options">
<h1>Options</h1>
{{> quickForm collection="Options" doc=this id="optionsForm" type=formType omitFields="owner"}}
</template>
Everything should work now. If the database doesn't give a value back, the form will automatically switch to insert. So in my example, if you open the form the first time, it will use insert. The second time, it will use update.
thanks #peXd. this was very helpful. however I had an additional required field in my schema which was blocking the insert and it was silently failing to insert and since i stumbled into this solution through 8 trap doors i thought i'd post it in case it helps someone else.
i found this recommendation from aldeed [https://github.com/aldeed/meteor-autoform/issues/199] to use this error hook in client code:
AutoForm.addHooks(null, {
onError: function (name, error, template) {
console.log(name + " error:", error);
}
});
however this also failed with me saying AutoForm was not defined. this was odd to me because aldeed:autoform was being pulled into the project as a dependency. but just to double check i did meteor add aldeed:autoform to pull it in directly and suddenly AutoForm was available to add the hook to.

Symfony UniqueEntity Constraint and javascript

i'm new to symfony, and don't know much about javascript!
i created a symfony form, and added a UniqueEntity constraint on the name and firstname, so it's not possible to add a same person twice in the database.
#UniqueEntity(fields={"firstname","name"}, message="this person already exists")
it works pretty well!
but in this case, i would like symfony to show me a javascript window with a message and 2 choices. for example: "joe smiley already exists! would you like to add an homonym? yes / no
does anyone know how to do this?
Much thanks
No, this validation is strictly server-side.
You should try some JS validation libraries like: http://rickharrison.github.io/validate.js/ (just an example)
well you could try to find if is there and error message for that field, and that will depend on how are you displaying your form fields, i strongly strongly recommend you to customize your form rendering to suit your needs, here is and example of what can you do.
<div class="control-group {% if(form_errors(form.descripcion)|length) %} error {% endif %} ">
{{ form_label(form.descripcion, null, { 'label_attr': {'class': 'control-label'} }) }}
<div class="controls">
{{ form_widget(form.descripcion) }}
{{ form_errors(form.descripcion) }}
</div>
</div>
that will render this when the validation shows and error message
<div class="control-group error ">
<label class="control-label required" for="AreaComercio_descripcion">Descripcion</label>
<div class="controls">
<input type="text" id="AreaComercio_descripcion" name="AreaComercio[descripcion]" required="required" >
<span class="help-inline">This value should not be blank.</span>
</div>
</div>
so you have to ask if is there an span sibling with the class help-inline if you dont know how to custimze your form rendering take a look at this and another advice use jquery, there are lots of people using it, jquery have an strong comunity that will help you if you are in the need, that said, i will use jquery to ilustrate what you can do to solve your problem.
if($("#AreaComercio_descripcion ~ .help-inline").length) { // here using sibling selector filter to ask if there a siblig with the class help-inline
var invalid_value = $("#AreaComercio_descripcion").val(); // asking for the field value thru its id attribute
confirm(invalid_value+" already exists! would you like to add an homonym ?");
}
using javascript confirm is the easiest way to do what you want but you can use other more flexible options like jquery dialog or you could try to install twitter bootstrap in your symfony installation, well i guess thats all i hope it will be usefull to you

Categories

Resources