Display error message in Modal using Ajax, laravel - javascript

I'm new to Laravel, I have a problem displaying errors on my project. I'm using laravel request for validation and AJAX to submit form inside a modal.
I would like to see the error message for each field that are inputted incorrectly. However, I'm getting this error:
The Given data is invalid
I checked the network tab, and I'm seeing the errors there but I can't figure out why this is not showing in my fields.
Here's the error:
Here's my Ajax
//add user code here
$(document).on("click", "#addUserBtn", function (e) {
e.preventDefault();
const first_name = $("#addModal [name=first_name]").val();
const middle_name = $("#addModal [name=middle_name]").val();
const last_name = $("#addModal [name=last_name]").val();
const email = $("#addModal [name=email]").val();
const cellphone = $("#addModal [name=cellphone]").val();
const userType = $("#addModal [name=user_type]").val();
const payload = {
first_name: first_name,
middle_name: middle_name,
last_name: last_name,
email,
cellphone,
user_type: userType
}
$("#addModal .fa-spinner").removeClass('d-none');
$.ajax({
url: "/users-listing",
data: payload,
type: "POST",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
}).done(function(res) {
$("#addModal .fa-spinner").addClass('d-none');
$("#addModal .form-message-container").html(res.message).addClass('text-success').fadeIn(1000);
table.draw(false);
setTimeout(() => {
$("#addModal .form-message-container").html('').removeClass('text-success').fadeOut();
$("#addModal [name=first_name]").val('');
$("#addModal [name=middle_name]").val('');
$("#addModal [name=last_name]").val('');
$("#addModal [name=email]").val('');
$("#addModal [name=cellphone]").val('');
$("#addModal #closeModal").click();
}, 3000);
}).fail(function(err) {
$("#addModal .fa-spinner").addClass('d-none');
$("#addModal .form-message-container").html(err.responseJSON.message).addClass('text-danger').fadeIn(5000);
setTimeout(() => {
$("#addModal .form-message-container").html('').removeClass('text-danger').fadeOut();
}, 5000);
});
});
// code end here
Here's my controller "Store"
public function store(UserRequest $request)
{
$data = $request->all();
$data['password'] = Hash::make(Str::random(10));
$data['status'] = 1;
$user = User::create($data);
$user->sendPasswordResetNotification(Str::random(60));
return response()->json(['code' => 200, 'message' => 'User added succesfully'], 200);
exit;
}
Request code
public function rules()
{
return [
'id' => 'bail|nullable',
'first_name' => 'required|string|min:2',
'middle_name' => 'string|nullable',
'last_name' => 'required|string|min:2',
'user_type' => 'required',
'cellphone' => ['nullable','max:15', Rule::unique('users', 'cellphone')->whereNull('deleted_at')->ignore($this->id, 'id')],
'email' => ['required', 'email', Rule::unique('users', 'email')->whereNull('deleted_at')->ignore($this->id, 'id')],
'status' => 'numeric'
];
}
My blade code
<div class="modal-body m-2">
<form id="adduserForm">
{{ csrf_field() }}
<div class="row form-group">
<div class="col">
<label>First name</label>
<input name="first_name" id="first_name" type="text" class="form-control" placeholder="" autocomplete="off">
</div>
<div class="col">
<label>Middle name</label>
<input name="middle_name" type="text" id="middle_name" class="form-control" placeholder="" autocomplete="off">
</div>
</div>
<div class="row form-group">
<div class="col">
<label>Last name</label>
<input name="last_name" type="text" id="last_name" class="form-control" placeholder="" autocomplete="off">
</div>
<div class="col">
<label>Email</label>
<input name="email" type="email" id="email" class="form-control" placeholder="" autocomplete="off">
</div>
</div>
<div class="row form-group">
<div class="col">
<label>Cellphone</label>
<input name="cellphone" type="number" id="cellphone" class="form-control" placeholder="" autocomplete="off">
</div>
</div>
<div class="row form-group">
<div class="col">
<label>User Type</label>
<select name="user_type" class="form-control form2 selectpicker" data-style="btn btn-secondary">
<option value="0">Property Owner</option>
<option value="1">Admin</option>
<option value="2">Treasury</option>
<option value="3">Assessor</option>
</select>
</div>
</div>
<div class="row form-group text-right mt-3">
<div class="col">
<div class="form-message-container text-left">
<span class="form-message"></span>
</div>
</div>
<div class="col">
<button id="closeModal" type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button id="addUserBtn" type="button" class="btn btn-primary right">
<span class="fa fa-spin fa-spinner mr-1 d-none"></span> Save Changes</button>
</div>
</div>
</form>
</div>

Add in your blade to every field:
<!-- ... -->
<div class="col">
<label>First name</label>
<div class="validation-message"></div>
<input name="first_name" id="first_name" type="text" class="form-control" placeholder="" autocomplete="off">
</div>
<!-- ... -->
And to your js:
// ...
$.ajax({
url: "/users-listing",
data: payload,
type: "POST",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
}).done(function(res) {
$("#addModal .fa-spinner").addClass('d-none');
$("#addModal .form-message-container").html(res.message).addClass('text-success').fadeIn(1000);
table.draw(false);
setTimeout(() => {
$("#addModal .form-message-container").html('').removeClass('text-success').fadeOut();
$("#addModal [name=first_name]").val('');
$("#addModal [name=middle_name]").val('');
$("#addModal [name=last_name]").val('');
$("#addModal [name=email]").val('');
$("#addModal [name=cellphone]").val('');
$("#addModal #closeModal").click();
}, 3000);
}).fail(function(err) {
$("#addModal .fa-spinner").addClass('d-none');
$("#addModal .form-message-container").html(err.responseJSON.message).addClass('text-danger').fadeIn(5000);
setTimeout(() => {
$("#addModal .form-message-container").html('').removeClass('text-danger').fadeOut();
}, 5000);
for (var [ el, message ] of Object.entries(err.responseJSON.errors)) {
$('#' + el).addClass('is-invalid');
$('#' + el).prev('.validation-message').text(message).addClass('is-invalid');
}
});
// ...

I was able to solve this by changing my route, and the error handling in AJAX.
Thanks for all the inputs ideas here. :)
My fix:
AJAX error code

Related

Laravel 9 upload image with ajax validation jQuery error

Whats wrong with my code? i use laravel 9, ajax, jQuery validation, and everytime i click submit, always show error like the one below appears
This display error:
{message: "validation.required (and 2 more errors)",…}
errors: {first_name: ["validation.required"], last_name: ["validation.required"],…}
message: "validation.required (and 2 more errors)"
My Controller:
public function store(Request $request)
{
$request->validate([
'first_name' => 'required',
'last_name' => 'required',
'image' => 'required|mimes:jpg,jpeg,png|max:1024',
]);
$file = Request()->file('image');
$file_name = Str::random(20) . '.' . $file->getClientOriginalExtension();
$file->move(public_path('images'), $file_name);
$form_data = [
'first_name' => $request->first_name,
'last_name' => $request->last_name,
'image' => $file_name
];
AjaxCrud::create($form_data);
return response()->json(['success' => 'Data added successfully.']);
}
My Route:
Route::get('/', [AjaxCrudController::class, 'index']);
Route::resource('ajax-crud', AjaxCrudController::class);
My Form:
<div class="modal fade" id="addmodal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Add Form</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="javascript:void(0)" name="addmodal" id="addform" class="form-horizontal"
enctype="multipart/form-data">
#csrf
<div class="mb-3">
<label for="first_name" class="form-label">First Name</label>
<input type="text" class="form-control" name="first_name" id="first_name" required>
</div>
<div class="mb-3">
<label for="last_name" class="form-label">Last Name</label>
<input type="text" class="form-control" name="last_name" id="last_name" required>
</div>
<div class="mb-3">
<label for="image" class="form-label">Select Profile Image</label>
<input type="file" class="form-control" name="image" id="image" required>
</div>
<div class="modal-footer">
<input type="submit" name="addbutton" id="addbutton" class="btn btn-primary" value="Add" />
<button type="button" class="btn btn-warning" data-bs-dismiss="modal">Close</button>
</div>
</form>
</div>
</div>
</div>
</div>
My Script:
<script>
$(document).ready(function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
// Add modal
$('#create_record').click(function(){
$('#addmodal').modal('show');
$('.modal-title').text('Add New Record');
$('#addbutton').val('Add');
$('#addaction').val('Add');
});
// Save Data
if ($('#addform').length > 0) {
$('#addform').validate({
rules: {
first_name: 'required',
last_name: 'required',
image: 'required',
},
messages: {
first_name: 'First name required!',
last_name: 'Last name required!',
image: 'Image required!',
},
submitHandler: function (form) {
event.preventDefault();
$.ajax({
data: $('#addform').serialize(),
url:'{{ route('ajax-crud.store') }}',
method:'POST',
contentType: false,
cache:false,
processData: false,
dataType:'json',
success:function(data)
{
$('#addform')[0].reset();
$('#addmodal').modal('hide');
$('#user_table').DataTable().ajax.reload();
iziToast.success({
title: 'Data added successfully.',
message: '{{ Session('success')}}',
position: 'topCenter'
});
}
})
}
});
}
});
</script>
......................................................................................................

Trying to submit and validate a form, but it hangs with error - title: ValidatorError: Path `title` is required

I'm new to JS and MongoDB and am trying to put together a simple CMS. I'm getting the following error:
title: ValidatorError: Path `title` is required.
{
properties: [Object],
kind: 'required',
path: 'title',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true }
Here is my controller:
const { restart } = require("nodemon");
const Post = require('../models/postModel').Post;
module.exports = {
index: (req, res) => {
res.render('admin/index');
},
getPosts: (req, res) => {
res.render('admin/posts/index');
},
submitPosts: (req, res) => {
console.log(req.body);
const newPost = new Post({
title: req.body.title,
description: req.body.description,
status: req.body.status
});
newPost.save().then(post => {
console.log(post);
req.flash('success-message', 'Post created successfully.');
res.redirect('/admin/posts');
}, err => console.log(err))
},
createPosts: (req, res) => {
res.render('admin/posts/create');
}
};
This is my post model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const PostSchema = new Schema({
title: {
type: String,
required: true
},
status: {
type: String,
default: 'public'
},
creationDate: {
type: Date,
default: Date.now()
}
})
module.exports = {Post: mongoose.model('post', PostSchema)};
and this is the HTML form I'm trying to submit:
<div class="container">
<h1>Create New Post</h1>
<div class="row p-4">
<div class="col-md-10">
<form action="/admin/posts/create" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" name="title" id="title" placeholder="Enter The Title">
</div>
<div class="form-group">
<label for="file">File Upload</label>
<input type="file" class="form-control" id="file" name="uploadedFile" accept="image/jpeg, image/jpg, image/png, image/bmp">
</div>
<div class="form-group">
<label for="status">Status</label>
<select name="status" id="status" class="form-control">
<option value="public">Public</option>
<option value="private">Private</option>
<option value="draft">Draft</option>
</select>
</div>
<div class="form-group">
<label for="category">Category</label>
<select name="category" id="category" class="form-control">
{{#each categories}}
<option value="{{_id}}">{{title}}</option>
{{/each}}
</select>
</div>
<div class="form-check ml-3">
<label for="allowComments">
<input type="checkbox" class="form-check-input" id="allowComments" name="allowComments">
Allow Comments
</label>
</div>
<div class="form-group">
<label for="description">Content</label>
<textarea name="description" id="description" class="form-control" placeholder="Enter your content here" rows="10"></textarea>
</div>
<button class="btn btn-outline-success btn-lg" type="submit">Create Post</button>
</form>
</div>
</div>
</div>
Can someone please help me find the problem? I've been trying to figure this out for days... thank you so much!

Fetch API POST, not sending <form> data

I keep getting a 500 error server when I try to submit form data to my API /users/signup. I verified that the API works using Postman so I think the way I am doing my fetch post is wrong. What is the best practice here?
JS
document.getElementById("create_user").addEventListener("click", (e) => {
e.preventDefault();
const signup = {
username: document.querySelector("#create_username").value.toString(),
email: document.querySelector("#create_email").value.toString(),
password: document.querySelector("#create_password").value.toString()
}
const data = new FormData();
data.append("json", JSON.stringify(signup));
fetch('/users/signup', {
method: 'POST',
body: data
})
.then((response) => response.json())
.catch((error) => {
console.error('Error:', error);
});
});
HTML
<form class="hide" id="sign_up_form">
<div class="form-row">
<h3>Sign up</h3>
</div>
<div class="form-row">
<div class="form-group col">
<label for="create_username">Username</label>
<input id="create_username" name="username" type="text" class="form-control" placeholder="Username">
</div>
</div>
<div class="form-row">
<div class="form-group col">
<label for="create_email">Email</label>
<input id="create_email" name="email" type="email" class="form-control" placeholder="Email">
</div>
</div>
<div class="form-row">
<div class="form-group col">
<label for="create_password">Password</label>
<input id="create_password" name="password" type="password" class="form-control" placeholder="Password">
<small id="passwordHelp" class="text-muted">
Must be at least 8 characters long
</small>
</div>
</div>
<div class="form-row flex-end">
<div class="form-group col-auto">
<button id="create_user" type="submit" class="btn btn-warning mb-2">Sign up</button>
</div>
</div>
<div class="form-row">
<span class="mr-2">Already have an account?</span>Login
</div>
</form>
You don't need to create a form object, you can directly send the json data to your backend.
Add yous json data in the body and the 'Content-Type': 'application/json' header in the request.
The value property of the querySelector method will always return string, you don't need to call toString method on it.
Try this.
document.getElementById("create_user").addEventListener("click", (e) => {
e.preventDefault();
const signup = {
username: document.querySelector("#create_username").value,
email: document.querySelector("#create_email").value,
password: document.querySelector("#create_password").value
}
fetch('/users/signup', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(signup)
})
.then((response) => response.json())
.then(data => console.log(data))
.catch((error) => {
console.error('Error:', error);
});
});

Stripe implementation in my own form in an Express app

I'm trying to get some value(total = total + itemJson.price * item.quantity) into my own form for stripe.
Every time I try to submit I get this error message:
"$ node server.js
C:\Users\Marcio\dsdrucker1\server.js:44 req.body.items.forEach(function(item) {
^
TypeError: Cannot read property 'forEach' of undefined
at C:\Users\Marcio\dsdrucker1\server.js:44:22
at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3)".
Here below you can find my code I have written. What am I doing wrong?
app.post('/checkout', function(req, res) {
fs.readFile('items.json', function(error, data) {
if (error) {
res.status(500).end()
} else {
const itemsJson = JSON.parse(data)
const itemsArray = itemsJson.roupa
let total = 0
req.body.items.forEach(function(item) {
const itemJson = itemsArray.find(function(i) {
return i.id == item.id
})
total = total + itemJson.price * item.quantity
})
stripe.charges.create({
amount: total,
source: req.body.stripeTokenId,
currency: 'usd'
}).then(function() {
console.log('Charge Successful')
res.json({ message: 'Successfully purchased items' })
}).catch(function() {
console.log('Charge Fail')
res.status(500).end()
})
}
})
})
<div class="col-sm-6 col-md-4 col-md-offset-4 col-sm-offset-3">
<h1>Checkout</h1>
<h4>Your Total: ${{total}}</h4>
<div id="charge-error" class="alert alert-danger {{#if noError}}hidden{{/if}}">
{{errMsg}}
</div>
<form action="/checkout" method="post" id="checkout-form">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" class="form-control" required name="name">
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="address">Address</label>
<input type="text" id="address" class="form-control" required name="address">
</div>
</div>
<hr>
<div class="col-xs-12">
<div class="form-group">
<label for="card-name">Card Holder Name</label>
<input type="text" id="card-name" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="card-number">Credit Card Number</label>
<input type="text" id="card-number" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="row">
<div class="col-xs-6">
<div class="form-group">
<label for="card-expiry-month">Expiration Month</label>
<input type="text" id="card-expiry-month" class="form-control" required>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="card-expiry-year">Expiration Year</label>
<input type="text" id="card-expiry-year" class="form-control" required>
</div>
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="card-cvc">CVC</label>
<input type="text" id="card-cvc" class="form-control" required>
</div>
</div>
</div>
<button type="submit" class="btn btn-success">Buy now</button>
</form>
</div>
</div>
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript" src="checkout.js"></script>
This is the Js I used for my form
Stripe.setPublishableKey('pk_test_BDlJ33LBsh5s6L69P5y3AAvp00ETkWe6tP');
var $form = $('#checkout-form');
$form.submit(function (event) {
$('#charge-error').addClass('hidden');
$form.find('button').prop('disabled', true);
Stripe.card.createToken({
number: $('#card-number').val(),
cvc: $('#card-cvc').val(),
exp_month: $('#card-expiry-month').val(),
exp_year: $('#card-expiry-year').val(),
name: $('#card-name').val()
}, stripeResponseHandler);
return false;
});
function stripeResponseHandler(status, response) {
if (response.error) { // Problem!
// Show the errors on the form
$('#charge-error').text(response.error.message);
$('#charge-error').removeClass('hidden');
$form.find('button').prop('disabled', false); // Re-enable submission
} else { // Token was created!
// Get the token ID:
var token = response.id;
// Insert the token into the form so it gets submitted to the server:
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// Submit the form:
$form.get(0).submit();
}
}

Vue.js 2 levels of nested form and checkboxes from json

In my Vue.js frontend app I wanted to create form to POST json data to REST API. The form has one part where I GET json data from API which is list of possible to add groups.
Vue.js code looks like
<script>
export default {
data () {
return {
line: {
name: '',
buttons: [{
name: '',
state: false,
is_reported: '',
assignmentGroups: [{
name: ''
}]
}]
},
assignmentGroupsList: []
}
},
methods: {
addButton () {
this.line.buttons.push({
name: '',
state: false,
is_reported: ''
})
},
deleteButton (index) {
this.line.buttons.splice(index, 1)
},
saveLine () {
// this.$http.post('http://127.0.0.1:8001/api/line')
// .then(response => response.json())
// .then(result => this.lines = result)
console.log(JSON.stringify(this.line))
},
fetchAssignmentGroups() {
this.$http.get('http://127.0.0.1:8001/api/agroup')
.then(response => response.json())
.then(result => this.assignmentGroupsList = result)
.then(result => console.log(result))
}
},
created: function () {
this.fetchAssignmentGroups();
//this.fetchLines();
}
}
</script>
and template
<template>
<div>
<div id="page-wrapper">
<div class="row">
<div class="col-lg-12">
<div class="form">
<div class="form-group">
<label for="name">Line name</label>
<input v-model="line.name" class="form-control" type="text" id="name" name="name"/>
</div>
<label for="">Buttons</label>
<div class="" v-for="(button, index ) in line.buttons">
<div class="form-group">
<label for="btn">Przycisk nr {{ index }}</label>
<input v-model="button.name" class="form-control col-lg-3" type="text" id="btn" name="btn" />
<input type="radio" id="'one' + index" :value="false" v-model="button.is_reported">
<label for="one">No</label>
<input type="radio" id="'two' + index" :value="true" v-model="button.is_reported">
<label for="two">Yes</label>
</div>
<div class="form-group">
<div class="" v-for="(agroup, index2) in assignmentGroupsList">
<input type="checkbox" :name="'agroup'+index2" :value=" agroup.name " v-model="button.assignmentGroups">
<label for="">{{ agroup.name }}</label>
</div>
</div>
<button class="btn btn-danger"
#click="deleteButton(index)">
Remove
</button>
</div>
<div class="form-group">
<button class="btn btn-success"
#click="addButton">
Add
</button>
<button class="btn btn-primary"
#click="saveLine">
Save
</button>
</div>
</div>
<!-- /.col-lg-12 -->
</div>
<!-- /.row -->
</div>
</div>
</div>
</template>
In browser I can see correctly list of groups in every added button but its all. It doesn't get data.

Categories