I am working on a Users CRUD application with Vue 3. I run into trouble while trying to validate the data in the "Add New User" form.
More precisely, I use the function below to make sure no form field is empy:
isNotEmpty() {
return (
this.formData.first_name &&
this.formData.last_name &&
this.formData.email
);
}
For a reason I could not figure out, the formErrors
array looks like this ["The email is invalid"]
instead of ["There are empty filelds","The email is invalid"]
;
const usersApp = {
data() {
return {
users: [{
id: 1,
first_name: "John",
last_name: "Doe",
email: "[email protected]"
},
{
id: 2,
first_name: "Jane",
last_name: "Doe",
email: "[email protected]"
}
],
formData: {
first_name: "",
last_name: "",
email: ""
},
formErrors: [],
userAdded: false
};
},
methods: {
isNotEmpty() {
return (
this.formData.first_name &&
this.formData.last_name &&
this.formData.email
);
},
isEmail(email) {
return String(email)
.toLowerCase()
.match(
/^(([^<>()[]\.,;:s@"]+(.[^<>()[]\.,;:s@"]+)*)|(".+"))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/
);
},
formValidation() {
this.formErrors = [];
if (!this.isNotEmpty) {
this.formErrors.push("There are empty filelds");
}
if (!this.isEmail(this.formData.email)) {
this.formErrors.push("The email is invalid");
}
console.log(this.formErrors);
},
resetAddFormData() {
this.formData.first_name = "";
this.formData.last_name = "";
this.formData.email = "";
this.userAdded = false;
},
addUser() {
// Validate form data
this.formValidation();
// Make New User
let newUser = {
first_name: this.formData.first_name,
last_name: this.formData.last_name,
email: this.formData.email
};
// Add new user
if (this.formErrors.length == 0) {
this.users.push(newUser);
this.userAdded = true;
window.setTimeout(this.resetAddFormData, 1000);
}
}
},
watch: {
users() {
this.users();
}
}
};
Vue.createApp(usersApp).mount("#app");
.logo {
width: 30px;
}
.nav-item {
width: 100%;
}
@media (min-width: 768px) {
.nav-item {
width: auto;
}
}
.users-table-item-active {
transition: opacity 2s ease;
opacity: 0;
}
.users-table-item {
opacity: 1;
}
.alert {
padding: 0.6rem 0.75rem;
text-align: center;
font-weight: 600;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
<!-- Brand -->
<a class="navbar-brand p-0" href="#">
<img src="https://www.pngrepo.com/png/303293/180/bootstrap-4-logo.png" alt="" class="logo">
</a>
<!-- Links -->
<div class="navbar-nav w-100">
<ul class="navbar-nav ml-auto" id="navbarSupportedContent">
<li class="nav-item">
<button type="button" class="btn btn-sm btn-success" data-toggle="modal" data-target="#exampleModalCenter">
Add user
</button>
</li>
</ul>
</div>
</nav>
<div class="container">
<div class="card my-2">
<h5 class="card-header px-2">Users</h5>
<div class="card-body p-0">
<table class="table table-striped m-0">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody name="users-table" is="transition-group">
<tr v-for="user, key in users" :key="user.id">
<td>{{user.first_name}}</td>
<td>{{user.last_name}}</td>
<td>{{user.email}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal fade" id="exampleModalCenter" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title h6" id="exampleModalLongTitle">Add New User</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div v-if="this.formErrors.length > 0">
<div v-for="error in formErrors" class="alert alert-danger">
{{error}}
</div>
</div>
<div v-if="userAdded" class="alert alert-success">User added successfully!</div>
<form @submit.prevent="addUser" novalidate>
<div class="form-group mb-2">
<input type="text" class="form-control input-sm" placeholder="First name" v-model="formData.first_name">
</div>
<div class="form-group mb-2">
<input type="text" class="form-control input-sm" placeholder="Last name" v-model="formData.last_name">
</div>
<div class="form-group mb-2">
<input type="email" class="form-control input-sm" placeholder="Email address" v-model="formData.email">
</div>
<div class=" mt-2">
<button type="submit" class="btn btn-sm btn-block btn-success">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
2
Answers
it seems like you forgot to actually call the isNotEmpty function. Right now the code is checking if the variable isNotEmpty is defined, and inverting the statement.
Should be
Instead of using computed boolean to check if your form is valid, you can use rules within each field like so :
Define rules
Define rules in your
data
like :Add rules to your inputs
Check if your form is valid
Check if your form is valid with the condittion
this.$refs.myForm.validate()
(by specifying a ref to your form)