I am using Laravel + VueJS 3 to build a small project,
I use axios.put method for update details for single user in a table row via a modal, but I have problems when I click on submit button of a form inside a modal with axios.put, even I filled all data for all inputs but It still said the errors below, can you guys show me how can I fix this please?
Thanks!
ERROR
My backend:
public function updateUser(Request $req, User $user)
{
$req->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email,' . $user->id,
'password' => 'same:confirmPassword|max:64',
'roles' => 'required',
]);
$input = $req->all();
if (!empty($input['password'])) {
$input['password'] = Hash::make($input['password']);
} else {
$input = Arr::except($input, 'password');
}
$user->update($input);
$user->syncRoles($input['roles']);
return $this->sendResponse($user, 'Updated!');
}
My JS Code:
import axios from "axios";
let API_URL = "http://localhost:8000";
export default {
name: "manageUsers",
components: {},
data() {
return {
users: [],
userInfo: {
id: 0,
name: "",
username: "",
phone: "",
email: "",
password: "",
},
};
},
methods: {
refreshUsers() {
axios.get(`${API_URL}/api/users/allusers`).then((res) => {
this.users = res.data.data;
});
},
getUserInfo(user) {
axios
.get(`${API_URL}/api/users/show/` + user.id)
.then((res) => {
this.userInfo.id = res.data.data.id;
this.userInfo.name = res.data.data.name;
this.userInfo.email = res.data.data.email;
this.userInfo.username = res.data.data.username;
this.userInfo.phone = res.data.data.phone;
})
.catch((error) => {
console.log("ERRRR:: ", error.response.data);
});
},
updateUser() {
axios
.put(`${API_URL}/api/users/update/${this.userInfo.id}`)
.then((res) => {
this.refreshUsers();
alert(res.data);
})
.catch((error) => {
console.log("ERRRR:: ", error.response.data);
});
},
},
mounted() {
this.refreshUsers();
},
};
My VueJS template code:
<template>
<table class="table table-striped" id="datatable">
<tbody>
<tr v-for="(user, id) in users" :key="user.id">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.username }}</td>
<td class="text-right">
<button
class="btn btn-link btn-warning btn-icon btn-sm"
data-toggle="modal" data-target="#userEditModal"
#click="getUserInfo(user)">
<i class="tim-icons icon-pencil"></i>
</button>
</td>
</tr>
</tbody>
</table>
<!-- EDIT USER MODAL -->
<div class="modal modal-black fade" id="userEditModal" tabindex="-1" role="dialog"
aria-labelledby="userEditModal" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="userEditModal">
Edit user <strong class="text-primary">{{ userInfo.username }}</strong>
</h4>
<button type="button" class="close"
data-dismiss="modal" aria-hidden="true">
<i class="tim-icons icon-simple-remove"></i>
</button>
</div>
<form class="form-horizontal">
<div class="modal-body">
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Username</label>
<div class="col-md-9">
<div class="form-group">
<input type="text" class="form-control" name="username"
v-model="userInfo.username" />
</div>
</div>
</div>
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Name</label>
<div class="col-md-9">
<div class="form-group">
<input type="text" class="form-control" name="name"
v-model="userInfo.name" />
</div>
</div>
</div>
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Email</label>
<div class="col-md-9">
<div class="form-group">
<input type="email" name="email" class="form-control"
v-model="userInfo.email" />
</div>
</div>
</div>
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Roles</label>
<div class="col-md-9">
<div class="form-group">
<input type="roles" name="roles" class="form-control"
v-model="userInfo.roles" />
</div>
</div>
</div>
</div>
<div class="modal-footer d-flex flex-row">
<button type="button" class="btn btn-secondary" data-dismiss="modal">
Close
</button>
<button type="submit" class="btn btn-primary" data-dismiss="modal"
#click="updateUser()">
Save changes
</button>
</div>
</form>
</div>
</div>
</div>
<!-- END EDIT USER MODAL -->
</template>```
I think you're not passing any parameters to your put call. axios docs
example:
axios.put('https://httpbin.org/put', { hello: 'world' });
When an issue like this arises you can always check your network tab in your browser. to see what data is send to your server.
I have a bit frustrating problem, result that I have a select / option where I choose an item and then a modal is opened and just by clicking on Add / update to table, it just commits to the state "itemstabla", but result that when I give it to edit item in the table and the model is opened and I change, for example, quantity to another digit, the state "itemstabla" is updated without executing the commit, it should only be done when clicking on the modal button.
My store:
let store = {
state: {
token: localStorage.getItem('access_token') || null,
items: [],
itemstabla: [],
monedas: [],
impuestos: [],
venta: [],
estadotienda: '',
},
getters: {
loggedIn(state) {
return state.token !== null
},
},
mutations: {
EliminarItemTabla(state, item) {
var index = state.itemstabla.findIndex(c => c.id == item);
state.itemstabla.splice(index, 1);
},
retrieveToken(state, token) {
state.token = token
},
setmonedas(state, monedas) {
state.monedas = monedas
},
setventa(state, venta) {
state.venta = venta
},
setitemstabla(state, items) {
let found = state.itemstabla.find(item => item.id == items.id);
if(found) {
if(items.accion=='agregar') {
found.cantidad = parseInt(found.cantidad) + parseInt(items.cantidad)
}
else {
found.cantidad = parseInt(items.cantidad)
}
}
else {
state.itemstabla.push(items)
}
},
actualizaritemstabla(state) {
state.itemstabla.forEach(function (item) {
if ((state.venta.moneda_id == 'S/' && item.moneda == 'S/') || (state.venta.moneda_id == '$' && item.moneda == '$')) {
item.precio = parseFloat(item.precio).toFixed(2)
}
else if(state.venta.moneda_id == '$' && item.moneda == 'S/') {
item.moneda = '$'
item.precio = parseFloat(parseFloat(item.precio) / parseFloat(state.venta.tipocambio)).toFixed(2)
}
else if(state.venta.moneda_id == 'S/' && item.moneda == '$') {
item.moneda = 'S/'
item.precio = parseFloat(parseFloat(item.precio) * parseFloat(state.venta.tipocambio)).toFixed(2)
}
});
},
setimpuestos(state, impuestos) {
state.impuestos = impuestos
},
setmonedaid(state, moneda_id) {
state.venta.moneda_id = moneda_id
},
settipocambio(state, tipocambio) {
state.venta.tipocambio = tipocambio
},
destroyToken(state) {
state.token = null
}
},
actions: {
retrieveToken(context, credentials) {
return new Promise((resolve, reject) => {
axios.post('/api/login', {
username: credentials.username,
password: credentials.password,
})
.then(response => {
const token = response.data.access_token
localStorage.setItem('access_token', token)
context.commit('retrieveToken', token)
resolve(response)
})
.catch(error => {
reject(error)
})
})
},
destroyToken(context) {
if (context.getters.loggedIn){
return new Promise((resolve, reject) => {
axios.post('/api/logout', '', {
headers: { Authorization: "Bearer " + context.state.token }
})
.then(response => {
localStorage.removeItem('access_token')
context.commit('destroyToken')
resolve(response)
})
.catch(error => {
localStorage.removeItem('access_token')
context.commit('destroyToken')
reject(error)
})
})
}
}
}
}
export default store
My file Vue:
<template>
<div>
<!-- MODAL PARA EDITAR ITEM -->
<div class="modal fade" id="editarItem" tabindex="-1" role="dialog" aria-labelledby="editarItem" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Editar ítem</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group row">
<label for="cantidadEdit" class="col-sm-4 col-form-label col-form-label-sm font-weight-bold">Cantidad</label>
<div class="col-sm-8">
<div class="input-group">
<input v-model="item.cantidad" type="number" class="form-control text-center font-weight-bold h2" min="1" tabindex="1" onfocus="this.select();">
</div>
</div>
</div>
<div class="form-group row">
<label for="itemEdit" class="col-sm-4 col-form-label col-form-label-sm">Stock</label>
<div class="col-sm-8">
<input type="text" class="form-control text-center font-weight-bold h2" v-model="item.stock" disabled>
</div>
</div>
<div class="form-group row">
<label for="precioEdit" class="col-sm-4 col-form-label col-form-label-sm">Precio unitario<small class="text-muted" id="porcentajefinalprecio">+ {{item.primer_margen}}%</small></label>
<div class="col-sm-8">
<input v-model="item.precio" type="text" class="form-control font-weight-bold" tabindex="2" onfocus="this.select();">
</div>
</div>
<div class="form-group row">
<label for="" class="col-sm-4 col-form-label col-form-label-sm">Tipo de impuesto</label>
<div class="col-sm-8">
<select v-model="item.impuesto" class="imp custom-select" id="imp">
<option v-for="imp in impuestos" v-bind:key="imp.id" v-bind:value="imp.id">{{ imp.nombre }}</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="precioTotalEdit" class="col-sm-4 col-form-label col-form-label-sm">Subtotal <small id="simboloparatodos" class="text-muted">{{item.moneda_id}}</small></label>
<div class="col-sm-8">
<input type="text" v-model="subtotal" class="form-control form-control-sm" id="precioTotalEdit" onfocus="this.select();" readonly>
</div>
</div>
<div class="form-group row">
<label for="precioigvEdit" class="col-sm-4 col-form-label col-form-label-sm">I.G.V. </label>
<div class="col-sm-8">
<input type="text" v-model="igv" class="form-control form-control-sm" id="precioigvEdit" readonly>
</div>
</div>
<div class="form-group row">
<label for="descuentoEdit" class="col-sm-4 col-form-label col-form-label-sm">Descuento</label>
<div class="col-sm-8">
<input v-model="item.descuento" type="text" class="form-control form-control-sm" id="descuentoEdit" data-toggle="popover" data-placement="top" data-html="true" data-content="Para montos. Ej: 10<br>Para porcentajes agrega %. Ej: 10%" data-trigger="hover" tabindex="4" onfocus="this.select();">
</div>
</div>
<div class="form-group row">
<label for="precioSubtotalEdit" class="col-sm-4 col-form-label col-form-label-sm">Total <small id="simboloparatodos" class="text-muted">{{ moneda_id }}</small></label>
<div class="col-sm-8">
<input v-model="total" type="text" class="form-control font-weight-bold" id="precioSubtotalEdit" value="0" tabindex="5" onfocus="this.select();">
</div>
</div>
<div class="form-group row">
<label for="precio20Edit" class="col-sm-4 col-form-label col-form-label-sm">Precio <small class="text-muted" id="porcentajeinicial">+ {{item.primer_margen}}%</small></label>
<div class="col-sm-8">
<div id="margeninicialx">{{ item.masprimermargen }}</div>
</div>
</div>
<div class="form-group row">
<label for="precio35Edit" class="col-sm-4 col-form-label col-form-label-sm">Precio <small class="text-muted" id="porcentajefinal">+ {{item.segundo_margen}}%</small></label>
<div class="col-sm-8">
<div id="margenfinalx"> {{ item.massegundomargen }}</div>
</div>
</div>
<div class="form-group row">
<label for="itemEdit" class="col-sm-4 col-form-label col-form-label-sm">Item</label>
<div class="col-sm-8">
<small id="marcaEdit">{{ item.marca }}</small> {{ item.nombre }}<br><span class="text-muted small" title="códigos" id="codigoedit" v-for="cod in codigos" v-bind:key="cod.id">{{ cod.nombre_codigo }}-{{ cod.pivot.nombre }}<br></span>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-sm btn-primary" tabindex="5" #click="anadiritem">Añadir</button>
</div>
</div>
</div>
</div>
<!-- FIN DE MODAL PARA EDITAR ITEM -->
<!-- SECCION SELECCIONAR ITEM Y AGREGAR A LA TABLA -->
<div class="">
<div class="input-group input-group-sm mb-3">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-search"></i></span>
</div>
<div class="prefetch">
<input type="text" id="item" class="form-control typeahead" placeholder="Buscar item (Ctrl+.)" v-model.trim="q" #keyup.enter="buscaritem">
</div>
<div class="input-group-append">
<button class="btn btn-outline-secondary" id="button-addon2" disabled></button>
</div>
</div>
</div>
<table class="table table-striped table-hover table-sm table-responsive-md text-nowrap mt-3" id="detailFactura">
<thead>
<tr>
<th>Ítem</th>
<th class="text-right">Cnt.</th>
<th class="text-right">Costo U.</th>
<th></th>
<th class="text-right text-nowrap">
SubTotal
</th>
<th class="text-right text-nowrap">
I.G.V
</th>
<th class="text-right text-nowrap"><span class="text-muted">
Total
<div id="monedaText"></div>
</span></th>
</tr>
</thead>
<tbody>
<tr v-for="itemtabla in itemstabla" v-bind:key="itemtabla.id">
<td class="overflow-hidden" style="max-width: 299px; text-overflow: ellipsis">{{ item.nombre }} <small class="text-muted">({{ itemtabla.marca }})</small> </td>
<td class="text-right"><small class="text-muted mr-1" title="Unidades">{{ itemtabla.unidad }}</small>{{ itemtabla.cantidad }}</td>
<td class="text-right">{{ itemtabla.precio }}</td>
<td class="text-right">
<i class="fas fa-pencil-alt mr-2"></i>
<i class="far fa-trash-alt"></i>
</td>
<td class="text-right">{{ preciosegunmoneda(itemtabla.precio, itemtabla.moneda, itemtabla.cantidad, itemtabla.impuesto, itemtabla.descuento).subtotal }}</td>
<td class="text-right">{{ preciosegunmoneda(itemtabla.precio, itemtabla.moneda, itemtabla.cantidad, itemtabla.impuesto, itemtabla.descuento).igv }}</td>
<td class="text-right">{{ preciosegunmoneda(itemtabla.precio, itemtabla.moneda, itemtabla.cantidad, itemtabla.impuesto, itemtabla.descuento).total }}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2" class="text-right" id="cantidadItems">{{ itemstabla.length }} </td>
<td class="small font-weight-bolder">ítem(s)</td>
</tr>
</tfoot>
</table>
<!-- FIN DE SECCION SELECCIONAR ITEM Y AGREGAR A LA TABLA -->
</div>
</template>
<script>
import {
required,
minLength,
maxLength,
between
} from 'vuelidate/lib/validators'
import Bloodhound from 'corejs-typeahead/dist/bloodhound';
import typeahead from 'corejs-typeahead/dist/typeahead.jquery';
export default {
name: 'tabla-item',
props: {
tienda: Number,
},
data() {
return {
resource: 'venta',
error: false,
submitStatus: null,
isLoading: false,
fullPage: true,
q: '',
suggestions: null,
item: {},
}
},
created() {
},
mounted() {
let contextoVue = this
// Cargar los datos del typeahead en items
this.suggestions = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
identify: function (item) {
return item.id;
},
remote: {
url: '/item/records/' + this.tienda + '/' + '%QUERY',
wildcard: '%QUERY'
}
});
let inputEl = $('.prefetch input');
inputEl.typeahead({
minLength: 1,
highlight: true,
}, {
name: 'suggestions',
source: this.suggestions,
limit: 20,
display: 'label',
templates: {
suggestion: (data) => {
let codigos = data.codigos
let nuevoscodigos = ""
codigos.forEach(function (valor, indice, array) {
nuevoscodigos = nuevoscodigos + valor.pivot.nombre + ','
});
let nuevoprecio = ((parseFloat(contextoVue.preciosegunmoneda(data.precio, data.moneda,'1',data.impuesto_id).precio) * parseFloat(data.primer_margen) / 100) + parseFloat(contextoVue.preciosegunmoneda(data.precio, data.moneda,'1',data.impuesto_id).precio)).toFixed(2)
return `<div class="ss-suggestion">
<div class="codigos">
${data.nombre_marca} <span title="Código global"> - ${nuevoscodigos}</span>
<span title="Código de barras"></span>
</div>
<div class="searchproducto" style="text-transform: capitalize;">
<strong>${data.nombre}</strong>
</div>
<div class="d-flex mt-1"><div class="searchprice text-primary">${contextoVue.moneda_id}
<span id="pricechange">${nuevoprecio}</span></div>
<div class="searchstock flex-grow-1 text-danger"><b>Stock</b>:
<b style="color: red;">${data.stock}</b><b></b></div></div></div>`;
}
}
});
// Cuando se hace click en un item
$('.prefetch input').bind('typeahead:selected', function (evt, suggestion) {
$('#editarItem').modal('show')
let preciosegunmoneda = ((parseFloat(contextoVue.preciosegunmoneda(suggestion.precio, suggestion.moneda, '1', suggestion.impuesto_id).precio) * parseFloat(suggestion.primer_margen) / 100) + parseFloat(contextoVue.preciosegunmoneda(suggestion.precio, suggestion.moneda, '1', suggestion.impuesto_id).precio)).toFixed(2)
let massegundomargen = ((parseFloat(contextoVue.preciosegunmoneda(suggestion.precio, suggestion.moneda, '1', suggestion.impuesto_id).precio) * parseFloat(suggestion.segundo_margen) / 100) + parseFloat(contextoVue.preciosegunmoneda(suggestion.precio, suggestion.moneda, '1', suggestion.impuesto_id).precio)).toFixed(2)
contextoVue.item = {
id: suggestion.id,
stock: suggestion.stock,
nombre: suggestion.nombre,
precio: preciosegunmoneda,
marca: suggestion.nombre_marca,
impuesto: suggestion.impuesto_id,
primer_margen: suggestion.primer_margen,
segundo_margen: suggestion.segundo_margen,
masprimermargen: preciosegunmoneda,
massegundomargen: massegundomargen,
codigos: suggestion.codigos,
cantidad: '1',
descuento: '0',
moneda: contextoVue.moneda_id,
unidad: suggestion.nombre_unidad,
}
});
// Fin typeahead items
},
updated() {
},
computed: {
total() {
return this.item.precio * this.item.cantidad - this.item.descuento
},
igv() {
if(this.item.impuesto=="1") {
return (parseFloat(this.total) * 18/100).toFixed(2)
}
else {
return 0
}
},
subtotal() {
return (parseFloat(this.total) - this.igv).toFixed(2)
},
tipocambio: {
get() {
return this.$store.state.venta.tipocambio
},
set(value) {
this.$store.commit('settipocambio', value)
}
},
moneda_id: {
get() {
return this.$store.state.venta.moneda_id
},
set(value) {
this.$store.commit('setmonedaid', value)
}
},
itemstabla: {
get() {
return this.$store.state.itemstabla
},
},
impuestos: {
get() {
return this.$store.state.impuestos
},
},
},
watch: {
moneda_id: function (val) {
//this.$store.commit('actualizaritemstabla')
},
},
methods: {
submit() {},
preciosegunmoneda(precio, moneda, cantidad, impuesto, descuento) {
let total,nuevoprecio,subtotal,igv = 0
if ((this.moneda_id == 'S/' && moneda == 'S/') || (this.moneda_id == '$' && moneda == '$')) {
nuevoprecio = parseFloat(precio).toFixed(2)
total = parseFloat((parseFloat(precio) * cantidad) - descuento).toFixed(2)
igv = parseFloat((parseFloat(total) * (impuesto=='1' ? 18/100 : 0))).toFixed(2)
subtotal = parseFloat(total - igv).toFixed(2)
return {precio: nuevoprecio, total: total, igv: igv, subtotal: subtotal }
}
else if (this.moneda_id == 'S/' && moneda == '$') {
nuevoprecio = parseFloat(precio * this.tipocambio).toFixed(2)
total = parseFloat((parseFloat(precio * this.tipocambio) * cantidad) - descuento).toFixed(2)
igv = parseFloat((parseFloat(total) * (impuesto=='1' ? 18/100 : 0))).toFixed(2)
subtotal = parseFloat(total - igv).toFixed(2)
return {precio: nuevoprecio, total: total, igv: igv, subtotal: subtotal }
}
else if (this.moneda_id == '$' && moneda == 'S/') {
nuevoprecio = parseFloat(precio / this.tipocambio).toFixed(2)
total = parseFloat((parseFloat(precio / this.tipocambio) * cantidad) - descuento).toFixed(2)
igv = parseFloat((parseFloat(total) * (impuesto=='1' ? 18/100 : 0))).toFixed(2)
subtotal = parseFloat(total - igv).toFixed(2)
return {precio: nuevoprecio, total: total, igv: igv, subtotal: subtotal }
}
},
deleteitem(i) {
this.$store.commit('EliminarItemTabla', i);
},
editaritem(item) {
$('#editarItem').modal('show')
this.item = item
},
anadiritem(event) {
$('#editarItem').modal('hide')
this.$store.commit('setitemstabla', this.item )
},
},
validations: {
form: {
nombre_codigo: {
required,
},
}
}
}
</script>
With the use of editaritem like you do, I think you're actually passing the item itself, so it gets modified as it's a reference.
editaritem(item) {
$('#editarItem').modal('show')
this.item = { ...item } // or some way to copy the object
}
And after you finish edit, perform the actual update of the edited object.
Hopefully this is a newbie question.
I am using Vuelidate to validate my form and the form validations works fine, when the “send email” button is clicked.However on success, instead of showing me the successful message, the system shows that all the form controls have errors(This is because I have bound the name, email, message controls to their corresponding empty data elements).
What am I missing?
How can I fix this issue?
Contact.vue
<template>
<div>
<section class="slice slice-lg" id="sct_contact_form">
<div class="container">
<div class="mb-5 text-center">
<span class="badge badge-soft-info badge-pill badge-lg">
Contact
</span>
<h3 class=" mt-4">Send us a message</h3>
</div>
<div class="row justify-content-center">
<div class="col-lg-8">
<form>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="form-control-label">Name</label>
<input class="form-control" type="text" placeholder="Name" v-model="user.name" id="name" name="name" :class="{ 'is-invalid': submitted && $v.user.name.$error }" >
<div v-if="submitted && !$v.user.name.required" class="invalid-feedback">Name is required</div>
</div>
</div>
</div>
<div class="row align-items-center">
<div class="col-md-12">
<div class="form-group">
<label class="form-control-label">Email</label>
<input class="form-control" type="email" placeholder="email#example.com"
v-model="user.email" id="email" name="email" :class="{ 'is-invalid': submitted && $v.user.email.$error }" >
<div v-if="submitted && $v.user.email.$error" class="invalid-feedback">
<span v-if="!$v.user.email.required">Email is required</span>
<span v-if="!$v.user.email.email">Email is invalid</span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="form-control-label">Message</label>
<textarea class="form-control" data-toggle="autosize" placeholder="Tell us a few words ..." rows="3" style="overflow: hidden; overflow-wrap: break-word; resize: none; height: 96.9922px;"
v-model="user.message" id="message" name="message" :class="{ 'is-invalid': submitted && $v.user.message.$error }" ></textarea>
<div v-if="submitted && $v.user.message.$error" class="invalid-feedback">
<span v-if="!$v.user.message.required">Message is required</span>
<span v-if="!$v.user.message.minLength">Message must be at least 6 characters</span>
</div>
</div>
</div>
</div>
<div class="text-center mt-4">
<button type="button" class="btn btn-dark rounded-pill" v-on:click="SendEmail()">Send your message</button>
<span class="d-block mt-4 text-sm">We'll get back to you in 24-48 h.</span>
<div v-if="submitted" class="valid-feedback">
<span v-if="!$v.user.name.$error && !$v.user.email.$error && !$v.user.message.$error">Your email was send successfully. We'll get back to you in 24-48 h.</span>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
</div>
</template>
import { Email } from '../api/email.js';
import { required, email, minLength, sameAs } from "vuelidate/lib/validators";
export default {
name: "Contact",
components:{
},
data() {
return {
user: {
name: "",
email: "",
message: ""
},
submitted: false
};
},
validations: {
user: {
name: { required },
email: { required, email },
message: { required, minLength: minLength(6) }
}
},
methods: {
SendEmail() {
this.submitted = true;
this.$v.$touch();
if (this.$v.$invalid) {
return;
}
var nameWithEmailText="Email message from: "+ this.user.name + "\nEmail message: " + this.user.message;
var subject="Email from contact us page in common membership website";
Meteor.call('email.send', this.user.email, subject, nameWithEmailText);
this.user.name='';
this.user.email='';
this.user.message='';
}
}
}
You should wait for the Meteor.call() to complete, then reset the validation state.
For example
Meteor.call('email.send', this.user.email, subject, nameWithEmailText, (error, result) => {
this.user.name = ''
this.user.email = ''
this.user.message = ''
this.$v.$reset()
})
I'm using laravel + VueJS for front-end. I have a groups component to handle groups creation and groups permissions. I need to use two vForms: One to create groups, and the other to create / assign permissions for the group.
The problem is when I send the permissions form, laravel receives data of the first form, this i suppose is because I create that instance first. I think I should create two instances of vForm, but I do not know how. Is this possible?
My component code:
<template>
<div class="container">
<div class="row mt-5">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Grupos</h3>
<div class="card-tools">
<button class="btn btn-success" #click="newGroupModal" v-if="$can('groupscreate')"> <i class="fas fa-user-plus fa-fw"></i> Nuevo Grupo </button>
</div>
</div>
<!-- /.card-header -->
<div class="card-body table-responsive p-0">
<table class="table table-hover">
<tbody>
<tr>
<th>ID</th>
<th>Nombre</th>
<th>Fecha Alta</th>
<th>Fecha Act</th>
<th>Acc.</th>
</tr>
<tr v-for="group in groups" :key="groups.id">
<td>{{ group.id }}</td>
<td>{{ group.name }}</td>
<td>{{ group.created_at | formattedDate }}</td>
<td>{{ group.updated_at | formattedDate }}</td>
<td><i class="fas fa-edit"></i></td>
<td><i class="fas fa-key"></i></td>
</tr>
</tbody>
</table>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="groupModal" tabindex="-1" role="dialog" aria-labelledby="groupModal" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="groupModal">Nuevo Grupo</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form #submit.prevent="editMode ? updateGroup() : createGroup()">
<div class="modal-body">
<div class="form-group">
<input v-model="form.name" type="text" name="name" placeholder="Name"
class="form-control" :class="{ 'is-invalid': form.errors.has('name') }">
<has-error :form="form" field="name"></has-error>
</div>
</div>
<div class="modal-footer">
<button v-show="editMode" type="button" class="btn btn-danger" #click="deleteGroup" v-if="$can('groupsdelete')">Eliminar</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cerrar</button>
<button type="submit" class="btn btn-primary" v-if="$can('groupsedit')">Guardar</button>
</div>
</form>
</div>
</div>
</div>
<!-- Modal Permissions-->
<div class="modal fade" id="groupPermissionsModal" tabindex="-1" role="dialog" aria-labelledby="groupPermissionsModal" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="userModal">Permisos por Grupo</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form #submit.prevent="updateGroupPermissions()">
<div class="modal-body">
<div class="form-group">
<label class="control-label">Usuarios</label><br>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="usersview" value="usersview" v-model="groupPermissions">
<label class="form-check-label" for="usersview">Ver</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="userscreate" value="userscreate" v-model="groupPermissions">
<label class="form-check-label" for="userscreate">Crear</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="usersedit" value="usersedit" v-model="groupPermissions">
<label class="form-check-label" for="usersedit">Editar</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="usersdelete" value="usersdelete" v-model="groupPermissions">
<label class="form-check-label" for="usersdelete">Eliminar</label>
</div>
</div>
<div class="form-group">
<label class="control-label">Grupos</label><br>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="groupsview" value="groupsview" v-model="groupPermissions">
<label class="form-check-label" for="groupsview">Ver</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="groupscreate" value="groupscreate" v-model="groupPermissions">
<label class="form-check-label" for="groupscreate">Crear</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="groupsedit" value="groupsedit" v-model="groupPermissions">
<label class="form-check-label" for="groupsedit">Editar</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="groupsdelete" value="groupsdelete" v-model="groupPermissions">
<label class="form-check-label" for="groupsdelete">Eliminar</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cerrar</button>
<button type="submit" class="btn btn-primary" v-if="$can('permissionsedit')">Guardar</button>
</div>
</form>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
editMode: false,
groups: {},
groupPermissions: {},
form: new Form({
id: '',
name : '',
}),
formPermissions: new Form({
users: [],
groups: []
}),
}
},
methods: {
newGroupModal(){
this.editMode = false;
this.form.reset();
$('#groupModal').modal('show');
},
newGroupPermissionsModal(groupId){
this.loadGroupPermissions(groupId);
this.form.reset();
$('#groupPermissionsModal').modal('show');
this.form.fill(this.groupPermissions);
},
newEditGroupModal(group){
this.editMode = true;
this.form.reset();
$('#groupModal').modal('show');
this.form.fill(group);
},
loadGroups(){
this.$Progress.start();
axios.get('api/group').then(({data}) => (this.groups = data.data));
this.$Progress.finish();
},
loadGroupPermissions(groupId){
this.$Progress.start();
axios.get('api/permissions/group/' + groupId).then(({data}) => (this.groupPermissions = data));
this.$Progress.finish();
},
createGroup(){
this.$Progress.start();
this.form.post('api/group')
.then(() => {
Fire.$emit('GroupInform');
$('#groupModal').modal('hide');
Toast.fire({
type: 'success',
title: 'Usuario creado satisfactoriamente.'
})
this.form.reset();
this.$Progress.finish();
})
.catch(() => {
this.$Progress.fail();
})
},
updateGroup(groupId){
this.$Progress.start();
this.form.put('api/group/' + this.form.id)
.then(() => {
Fire.$emit('GroupInform');
$('#groupModal').modal('hide');
Toast.fire({
type: 'success',
title: 'Usuario actualizado satisfactoriamente.'
})
this.form.reset();
this.$Progress.finish();
})
.catch(() => {
this.$Progress.fail();
})
},
deleteGroup(){
Swal.fire({
title: 'Estas seguro?',
text: "No podrás restaurar los datos eliminados.",
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#d33',
cancelButtonColor: '#14b750',
confirmButtonText: 'Si'
}).then((result) => {
if (result.value) {
this.form.delete('api/group/'+this.form.id).then(()=>{
Toast.fire({
type: 'success',
title: 'Usuario eliminado satisfactoriamente.'
})
Fire.$emit('GroupInform');
$('#groupModal').modal('hide');
}).catch(()=> {
Swal.fire("Error!", "Algo anda mal.", "warning");
this.$Progress.fail();
});
}
})
},
updateGroupPermissions(){
this.$Progress.start();
this.form.post('api/permissions/group/1')
.then(() => {
Fire.$emit('GroupInform');
$('#groupModal').modal('hide');
Toast.fire({
type: 'success',
title: 'Usuario actualizado satisfactoriamente.'
})
this.form.reset();
this.$Progress.finish();
})
.catch(() => {
this.$Progress.fail();
})
}
},
mounted() {
this.loadGroups();
Fire.$on('GroupInform', () => {
this.loadGroups();
});
}
}
</script>
Simply add a new variable with a different name than 'form' as a new instance from v-form
form2: new Form({
id: '',
name : '',
})
then access it like that:
<div class="form-group">
<input v-model="form2.name" type="text" name="name" placeholder="Name" class="form-control" :class="{ 'is-invalid': form.errors.has('name') }">
<has-error :form="form2" field="name"></has-error>
</div>
In my home page i have to create records and when i am creating the records and clicking on submit button and getting like added successfully. After that the created record is not available in the list records.When i'm creating another new record and submit it the previous created record is displays in the list.
Type Script code is:
import { Component, OnInit } from '#angular/core';
import {FormControl, Validators, NgForm } from '#angular/forms';
import { VisitService } from '../shared/visit.service';
import { ToastrService } from 'ngx-toastr';
import { Response, RequestOptions, Http, Headers } from '#angular/http';
import { CookieService } from 'ngx-cookie-service';
#Component({
selector: 'app-visit',
templateUrl: './visit.component.html',
styleUrls: ['./visit.component.css']
})
export class VisitComponent implements OnInit {
cookieValue = 'UNKNOWN';
constructor(private visitService: VisitService,private http: Http,private cookieService: CookieService, private toastr: ToastrService ) { }
ngOnInit() {
this.resetForm();
this.cookieValue = this.cookieService.get('session');
console.log('token from browser' + this.cookieValue );
const url = `http://localhost:8080//api/getallvisits/`;
// const headers = new Headers({'Content-Type': 'application/json','Authorization':'Bearer' +this.cookieValue});
let headers = new Headers({ 'Authorization': 'Bearer ' + this.cookieValue });
// const headers = new Headers();
// headers.append('Authorization', 'Bearer' +this.cookieValue );
const options = new RequestOptions({ headers: headers });
return this.http.get(url, options)
.subscribe(res => {
console.log('message from' + res);
// this.refresh();
alert('successfullyyy...');
// console.log('message from' + people.json())
});
}
resetForm(form?: NgForm) {
if (form != null)
form.reset();
this.visitService.selectedVisit = {
'ID':null,
'UserName': '',
'Height': null,
'Weight': null,
'Temperature': null,
'BloodPressure': '',
'PatientNote': '',
'NurseNote': '',
'DoctorNote': '',
}
}
onSubmit(form: NgForm) {
if (form.value.ID == null) {
this.visitService.createVisit(form.value)
.subscribe(data => {
this.resetForm(form);
this.visitService.getVisitList();
this.toastr.success('New Record Added Succcessfully', 'Employee Register');
})
}
else {
this.visitService.updateVisit(form.value.ID, form.value)
.subscribe(data => {
this.resetForm(form);
this.visitService.getVisitList();
this.toastr.info('Record Updated Successfully!', 'Employee Register');
});
}
}
}
And my HTML page is:
<form class="visit-form" #visitForm="ngForm" (ngSubmit)="onSubmit(visitForm)">
<input type="hidden" name="ID" #ID="ngModel" [(ngModel)]="visitService.selectedVisit.ID">
<div class="form-row">
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="UserName" name="UserName" #UserName="ngModel" [(ngModel)]="visitService.selectedVisit.username"
placeholder="User Name" required>
<div class="validation-error" *ngIf="UserName.invalid && UserName.touched">This Field is Required.</div>
</mat-form-field>
</div>
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Height" name="Height" #Height="ngModel" [(ngModel)]="visitService.selectedVisit.height" placeholder="Height"
required>
<div class="validation-error" *ngIf="Height.invalid && Height.touched">This Field is Required.</div>
</mat-form-field>
</div>
</div>
<div class="form-group">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Temperature" name="Temperature" #Temperature="ngModel" [(ngModel)]="visitService.selectedVisit.temperature" placeholder="Temperature">
</mat-form-field>
</div>
<div class="form-group">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Weight" name="Weight" #Weight="ngModel" [(ngModel)]="visitService.selectedVisit.weight" placeholder="Weight">
</mat-form-field>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Blood Pressure" name="BloodPressure" #BloodPressure="ngModel" [(ngModel)]="visitService.selectedVisit.bloodpressure" placeholder="Blood Pressure">
</mat-form-field>
</div>
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Patient Note" name="PatientNote" #PatientNote="ngModel" [(ngModel)]="visitService.selectedVisit.patientnote" placeholder="Patient Note">
</mat-form-field>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Nurse Note" name="NurseNote" #NurseNote="ngModel" [(ngModel)]="visitService.selectedVisit.nursenote" placeholder="Nurse Note">
</mat-form-field>
</div>
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Doctor Note" name="DoctorNote" #DoctorNote="ngModel" [(ngModel)]="visitService.selectedVisit.doctornote" placeholder="Doctor Note">
</mat-form-field>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-8">
<button [disabled]="!visitForm.valid" type="submit" class="btn btn-lg btn-block btn-info">
<i class="fa fa-floppy-o"></i> Submit</button>
</div>
<div class="form-group col-md-4">
<button type="button" class="btn btn-lg btn-block btn-secondary" (click)="resetForm(visitForm)">
<i class="fa fa-repeat"></i> Reset</button>
</div>
</div>
</form>
Anyone please refer that.Thank You
See if you are displaying the value in html table or like that then after submit you have to destroy the table .
and again Reinit the table then only it will display the current added value as well.
So You can do that or else call the onload function when submit function ends .
or if you have some other issue then let me know in details.