Showing error for multiple empty inputs vuejs vuetify - javascript

I have three inputs as externalIP as External Host, externalHttpPort as Port and vendor as Vendor, I want to show error message if any of them is missing. but being specific about the name,
if (!this.externalIP || !this.externalHttpPort || !this.vendor) {
when I do if condition, this works but I am not sure how I can tell if which input is empty. only one way which left is to add 3 multiple if
something like this
let error;
error = !this.externalIP
? "External IP Address (or URL) is incorrect"
: "" || !this.externalHttpPort
? "Port is missing" : "" || !this.vendor
? "Please choose camera vendor or add your camera snapshot URL." : ""
if (!error == "") {
this.setNotification({
text: error,
color: "warning",
snackbar: true
})
return
}
is there any other way of doing it? Also, Eslint show warning on indentations as well

In this way, you can achieve the same result as by your logic without using multiple if. Also, this way will keep your template & logic clean/easily scalable.
new Vue({
el: '#app',
data: {
fields: [
{
key: 'externalIP',
value: '',
validationMessage: 'External IP Address (or URL) is incorrect'
},
{
key: 'externalHttpPort',
value: '',
validationMessage: 'Port is missing'
},
{
key: 'vendor',
value: '',
validationMessage: 'Please choose camera vendor or add your camera snapshot URL.'
}
]
},
computed: {
getError () {
let e = ''
for (let i in this.fields) {
if (!this.fields[i].value) {
e = this.fields[i].validationMessage
break
}
}
return e
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input
v-for="(field, i) in fields"
:key="i"
v-model="fields[i].value"
/>
<br>{{ getError }}
</div>

Well, you may assign an error field variable within your error-checking condition.
Example for three variables and an emptyField variable denoting the empty variable name:
if ((!a && (emptyField = "a")) ||
(!b && (emptyField = "b")) ||
(!c && (emptyField = "c"))) {
alert("Field " + emptyField + " is empty...");
}
Since JS lazily evaluates its arguments, emptyField = "a" will get executed only if !a is true.
Just note that lazy evaluation also causes the evaluation of conditions stop once a condition was hit, thus if a is null and also b is null, the alert would announce that "Field a is empty..."

if vuetify you can use rules to check inputs
for example:
in your template:
<v-text-field
rules="[rules.required]"
/>
and in your data:
data() {
return {
rules: {
required: (value) => !!value || 'This field is required.'
}
}
},
you can add any other checking to rules array and just add it to your input by passing it to rules prop
hope it helps you!!!

I'm using VeeValidate to handle all of Validation job, maybe you will be interested in it:
https://logaretm.github.io/vee-validate/

Related

Vuelidate "required" ignoring value attributed in JS

I created a wizard form which uses Vuelidate to validate it's fields. The big majority of the fields have only the "required" function, so my validations are something close to this:
validations() {
if (this.currentStep === 0) {
return {
person: {
name: {
required,
},
age: {
required,
},
}
}
} else if (this.currentStep === 1) {
return {
person: {
street: {
required,
},
city: {
required,
},
state: {
required,
},
}
}
The thing is, I am receiving this data from an API, so the user can either fill the fields himself, or let the machine do it for him. When I receive the data, I make this attribution in a function in JS close to the following:
attributeData():
this.person.name = apiData.name;
this.person.age = apiData.age;
this.person.street = apiData.street;
this.person.city = apiData.city;
this.person.state = apiData.state;
If the user types the info, then everything works fine. If I receive the info from the API, then I get the error as if the input was empty.
This is how every field in my HTML is organized:
<b-form-group label="Name">
<b-form-input
v-model="person.name"
type="text"
size="sm"
:class="{
'is-invalid':
submitted && $v.person.name.$error,
}"
></b-form-input>
<div
v-if="submitted && $v.person.name.$error"
class="invalid-feedback"
>
<span v-if="!$v.person.name.required"
>Name is required.</span
>
</div>
</b-form-group>
Any idea of why Vuelidate can't recognize the values when I attribute them directly in JS? I've made this exact same way in another page and it worked. In DevTools even the $model of Vuelidate has the value that came from the API.
This error may occur if you have two elements using the same identifier.
Example:
data: {user_id: null} and setted v-model="user_id" in one input.
And another element input with: id:user_id
Beware if you are not manipulating the value and then it lost the reference, example:
data: {user: {name: null}}
And you filled it by API but latter in created or mounted put something like:
this.user = {}
The reference user.name was gone and validation can't work anymore.

Vuelidate never v.dirty always true even if all requirements are met

Showing only relevant code, if more is needed tell me.
My problem is that even when a name is entered to the text-field. I cannot go to the next card since !this.$v.$invalid never becomes false.. I have no idea what i am missing here..
Note that the errors are showing fine when clicked on the button without it having any value.
Vuelidate.js
import Vuelidate from 'vuelidate'
import VueTimepicker from 'vue-time-picker'
Vue.use(Vuelidate)
CardOne.js
import { validationMixin } from 'vuelidate'
import { required, maxLength ,email } from 'vuelidate/lib/validators'
mixins: [validationMixin],
validations: {
name: { required, name },
},
methods {
showNextCard(){
this.$v.$touch() //it will validate all fields
console.log(this.$v);
if (!this.$v.$invalid) { //invalid, becomes true when a validations return false
//you dont have validation error.So do what u want to do here
console.log("in here");
this.$emit("nextCard");
}
},
}
computed {
name: {
get () {
return this.$store.state.cardOne.name;
},
set (value) {
this.$store.commit('updateName', value)
}
},
nameErrors () {
const errors = []
if (!this.$v.name.$dirty) return errors
!this.$v.name.required && errors.push('Måste fyllas i')
return errors
},
}
CardOne.html
<div >
<form>
<v-text-field
v-model="name"
label="För- och efternamn"
required
#blur="$v.name.$touch()"
:error-messages="nameErrors"
:v="$v.name">
</v-text-field>
<v-btn
v-bind:style="[formCardIndexx === 0 ? {'margin-left': 'auto'} : {}]"
v-if="formCardIndexx != 10"
active-class="no-active"
class="next-button"
type="button"
:ripple="false"
#click="showNextCard()">
NÄSTA
</v-btn>
</form>
</div>
I saw that i had added that when i checked to see. But it did not help the problem. This is the v object printed right before it should validate the form.
In validations, you have:
validations: {
name: { required, name },
},
required makes sense and is a valid vuelidate built-in validator per https://vuelidate.js.org/#sub-builtin-validators. However, name doesn't. Unless you have a customer name validator defined somewhere in code you aren't showing, you should try removing that. It could be failing to validate because it can't validate against undefined, which from what I see in your code, name would surely evaluate to.
Try:
validations: {
name: { required },
},

How to handle Laravel to Vue.js boolean values

I've got an input field that looks like the following :
<tr v-for="(item, index) in collection">
...
<input
type="checkbox"
v-model="item.activated"
#change="toggleSwitch(item.resource_url, 'activated', item)">
>
...
</tr>
The collection is an array containing several keys, activated is one of them. activated is equal to 1 or 0 as the data is coming from a mysql database. The problem is that the input field is always set to true in this case, even if the activated is equal to 1 or 0.
Now, I tried writing the v-model like so to fix the issue :
v-model="!!+item.activated"
as by adding !!+ I'd convert the integer value to a boolean and use that. That fixes the issue, but creates another. The other issue I get by doing so is when I try to change my checked input I get an error :
[Vue warn]: Cannot set reactive property on undefined, null, or primitive value: false
admin.js:120238 TypeError: Cannot use 'in' operator to search for 'activated' in false
The toggleSwitch method looks like this :
toggleSwitch: function toggleSwitch(url, col, row) {
var _this8 = this;
axios.post(url, row).then(function (response) {
_this8.$notify({ type: 'success' });
}, function (error) {
row[col] = !row[col];
_this8.$notify({ type: 'error' });
});
},
I'm new to Vue.js, any idea how to debug this and where could my problem be coming from? I'll gladly give any additional info.
Edit :
Here's my component
Vue.component('profile-edit-profile-form', {
mixins: [AppForm],
data: function() {
return {
form: {
...
activated: false ,
...
}
}
}
});
If you use AJAX to populate your collection, then you should convert your 0 and 1 strings to booleans in your AJAX callback before injecting them into your component. Or even better you could convert them directly from your controller, by the way you directly get true|false
data.forEach(function(entry) {
if(entry.hasOwnProperty("activated"))
entry.activated = !!+entry.activated
});
my recommendation is:
Database column "activated" tinyint(1)
in laravel model use $cast array to cast "activated" to "boolean"
in vue use native type boolean for form.activated with true and false
Laravel Model:
protected $casts = [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'minimum' => 'float',
'maximum' => 'float',
'step' => 'float',
'minItems' => 'integer',
'maxItems' => 'integer',
'uniqueItems' => 'boolean',
];
Vue:
<b-form-radio-group id="uniqueItems" v-model="formData.uniqueItems" :options="optionsBoolean" name="uniqueItems" :/>
optionsBoolean (){
return [
{ text: 'Yes'), value: true },
{ text: 'No'), value: false }
]
}

Checking if null or whitespace in Vue

I have been in the process of teaching myself Vue.js and really like it so far. I have a project that I finally get the chance to use it on. I am creating a form and wanting to do some validations. I am used to the C# way of doing things, such as String.IsNullOrWhiteSpace() that just hits everything in one swoop. I haven't found a way to do that in Vue yet, if even possible. I do know of simpler ways to do it in regular javascript
This is my app and data
const app = new Vue({
el: '#app',
data() {
return {
errors: [],
parentInfo: {
name: null,
address: null,
city: null,
state: null,
zip: null,
primaryPhone: null,
secondaryPhone: null
}
}
}
...
Here are my validations for the form. This still does not catch if they add a whitespace to every field.
checkParentInfo: function () {
this.errors = [];
for (var i in this.parentInfo) {
if (this.parentInfo[i] === null && i !== 'secondaryPhone' || !this.parentInfo[i] && i !== 'secondaryPhone') {
this.errors.push('All parent info must be filled out, with the exception of a Secondary Phone Number');
return;
}
}
}
Is there a built in way to do my if statement? In one swoop like I can in C#?
Instead of if (this.parentInfo[i] === null) you can easily write if (!this.parentInfo[i]) which will be true when this.parentInfo[i] is anything but undefined, null, NaN, 0, "" (empty string) or false.
A string containing only a whitespace will return true, so you'll have to run if (this.parentInfo[i]===" ") for that.
You can of course create your own method IsNullOrWhiteSpace and use that instead.
Please also note that this is rather a Javascript question than a Vue.js question.

Conditional getInitialState- if value null

I am having some trouble with getInitialState in react. I have some data that arrives in my props, but it will not always have the key "text".
I want it to just give it an empty value if it doesn't find the props field "text"
I basically want to say
`this.props.photo.info[0].text OR if that doesn't exist, show ''
I tried this with
The below gives an invalid props error:
getInitialState() {
return {
value: ((this.props.photo && this.props.photo.info && this.props.photo.info[0].text) || '')
This gave the same error:
value:this.props.photo.info[0].text || 'empty'
If I do the below, all that gets returned is [Object, Object] which makes me think it is returning the value from the first this.props.photo or .info (ie not all the way to info[0].text)
(this.props.photo || this.props.photo.info || this.props.photo.info[0])
This is a sample of my json data in the props
{
"title": "Item 1",
"info": [
{
"text": "<h1> I'm a real value </h1> <br/> <p> Not always here</p>",
}
],
},
{
"title": "Item 2",
"info": [],
},
I can see why your second example would be [Object Object] but the first one looks like it should work to me, but you will get an error if there is no info[0]. Try the following? -
getInitialState() {
return {
value: ((this.props.photo && this.props.photo.info && this.props.photo.info[0] && this.props.photo.info[0].text) || '')
};
}
I often use default values, they can provide default values in a very elegant way.

Categories