When sending response code in laravel api, validation does not enter.
I can view it from the network, but when I send the status code, the console prints an error and I cannot print the validations on the blade page. If I don't send status code I can print validations.
Following my code: StudentController
public function store(Request $request): object
{
$validate = Validator::make($request->all(),[
'name' => 'required',
'course' => 'required',
]);
$data = [
'name' => $request->name,
'course' => $request->course,
];
if ($validate->fails()){
return response()->json(['success' => false, 'errors' => $validate->messages()->all()],422);
}
Student::insert($data);
return response()->json(['success' => true, 'message' => "Registration Successful"]);
}
ajax
$(document).ready(function (){
$('#createBtn').on('click',function (e) {
e.preventDefault();
let form = $('#student-add').serialize();
$.ajax({
'url': "{{ route('students.store') }}",
'data': form,
'type': "POST",
success:function (result) {
$('#ajax-validate ul').text("");
if(result.success === true){
console.log("True");
}else {
result.errors.forEach(function (item) {
$('#ajax-validate ul').append('<li>'+item+'</li>');
});
}
}
});
});
});
console
network
You have your response.errors.forEach inside of your success: function(), but 422 (or any 400) code doesn't get handled by the success function, but rather the error function:
$(document).ready(function () {
$('#createBtn').on('click', function (e) {
e.preventDefault();
let form = $('#student-add').serialize();
$.ajax({
url: "{{ route('students.store') }}",
data: form,
type: 'POST',
success: function (result) {
if (result.success === true) {
// Do whatever on `2XX` HTTP Codes
}
},
error: function (response) {
if (response.status === 422) {
let responseJson = response.responseJSON ? response.responseJSON : { errors: [] };
$('#ajax-validate ul').text('');
responseJson.errors.forEach(function (item) {
$('#ajax-validate ul').append('<li>'+item+'</li>');
});
} else {
console.log('Unhandled Error:', response)
}
}
});
});
});
Now when an 422 error is explicitly triggered, you code can properly handle the validation errors.
Related
I have an Angular form component which sends a http request and subscribes to that request. Now I'm trying to add a sweetalert2 feature to start a loader when the form is submitted (onSubmit()) and the http request is executed (with doSubmit()) and I'd like the sweetalert modal to change to a success or error message when http request returns a response which is subscribed to by the component (resulting in execution of onSuccess() or onError()). For some reason, my swal.preConfirm doesn't change the sweetalert from the loader to a success or error message. Can you please help?
protected doSubmit(): Observable<NewUser> {
swal.queue([{
title: 'Registration',
text: 'Processing your information',
onBeforeOpen: () => {
swal.showLoading()
},
preConfirm: () => {
return this.onSuccess()
.then(() =>
swal.insertQueueStep({
title: 'Success'
})
)
.catch(() =>
swal.insertQueueStep({
title: 'Error'
})
)
}
}])
return this.httpService.callDatabase<NewUser>('post', '/api/users/register', this.value)
}
onSubmit() {
if (this.form.valid) {
this.doSubmit().subscribe(
() => {
this.error = null;
this.onSuccess();
},
err => {
this.error = err
this.onError();
},
() => {
this.submitted = false;
this.completed = true;
}
)
}
}
onSuccess(){
return new Promise((resolve){
resolve('success')
})
onError(){
return new Promise((reject){
reject('error')
})
I figured out a bit of a make shift solution for this issue without using swal.preConfirm. Hopefully, there is a more elegant solution to achieving the same. For now, here's my solution:
protected doSubmit(): Observable<NewUser> {
this.invalidOnError = '';
this.navigationExtras = { queryParams: this.asssignToNavExtras.assignToNavExtras({ username: this.username.value }) };
swal.fire({
title: 'Registration',
text: 'Processing your information',
onBeforeOpen: () => {
swal.showLoading()
}
})
.then
return this.httpService.callDatabase<NewUser>('post', '/api/users/register', this.value)
};
onSubmit() {
if (this.form.valid) {
this.doSubmit().subscribe(
() => {
this.error = null;
this.onSuccess();
},
err => {
this.error = err
this.onError();
},
() => {
this.submitted = false;
this.completed = true;
}
)
}
}
protected onSuccess() {
swal.fire({
title: 'Registration Successful',
text: 'Thank you',
icon: 'success',
confirmButtonText: 'OK',
buttonsStyling: false,
customClass: {
confirmButton: 'btn'
},
timer: 10000,
})
}
protected onError() {
swal.fire({
showConfirmButton: false,
timer: 10,
onAfterClose: () => {
code for where to place focus after sweetalert is closed
}
})
}
I am trying to connect my react app with the backend for log in page. I am using a promise to return a success message.
login.js
onSubmitSignIn = () => {
fetch('http://localhost:5000/', {
method : 'post',
headers :{ 'Content-Type' : 'application/json'},
body : JSON.stringify({
userId : this.state.userId,
password : this.state.password
}).then(response => response.json())
.then(data => {
if(data === 'success'){
this.props.onRouteChange('home');
}
})
})
}
Backend code -
exports.findById = (req) => {
return new Promise((resolve) => {
var sql = "Select * from users where userid = '" + req.body.userId + "' ;";
connection.query(sql,req, function (error, results, fields) {
var data = JSON.parse(JSON.stringify(results));
var valid = false;
if( data.length !=0 && req.body.userId === data[0].userid && req.body.password === data[0].password)
valid = true;
if(valid) {
resolve({message : "success"});
}else{
reject({ message :"fail"});
}
});
})
};
After clicking on sign in button, I am getting an error "TypeError: JSON.stringify(...).then is not a function"
I tried some solutions from similar questions, it did not work in my case.
The then should be outside of fetch
fetch('http://localhost:5000/', {
method : 'post',
headers :{ 'Content-Type' : 'application/json'},
body : JSON.stringify({
userId : this.state.userId,
password : this.state.password
})
}).then(response => response.json())
.then(data => {
if(data === 'success'){
this.props.onRouteChange('home');
}
})
You have a typo, .then should be on fetch not on JSON.stringify.
onSubmitSignIn = () => {
fetch("http://localhost:5000/", {
method: "post",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
userId: this.state.userId,
password: this.state.password
})
})
//-^
.then(response => response.json())
.then(data => {
if (data === "success") {
this.props.onRouteChange("home");
}
});
};
you have missed a bracket. there should be a closing bracket after JSON.stringify().
onSubmitSignIn = () => {
fetch('http://localhost:5000/', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userId: this.state.userId,
password: this.state.password
})
}).then(response => response.json())
.then((data) => {
if (data === 'success') {
this.props.onRouteChange('home');
}
});
};
I had this problem too. Check and confirm that you're not importing or requiring {JSON} in your application. It's most likely referring to that imported JSON rather than the global
I have been able to change the activation status of companies in database on onClick event of the checkbox. Now I am not able to toggle the status of the checkbox, What I am missing Here?
I have looked on various sites, but could not find the solution.
Here is my code in which i am printing the companies.
{this.state.allCompanies.map(com => (
<tr>
<td>{com.cname} </td>
<td>
<a>
<input
type="checkbox"
name="active"
checked={com.is_active == 1 ? "true" : ""}
onClick={
(() => {
this.setState({ cked: !this.state.cked });
},
e => this.handleActivated(e, com.cid))
}
/>
</a>
</td>
</tr>
))}
Here is my function.
handleActivated(e, id) {
const comid = id;
var data = {
comid: id
};
console.log(data);
fetch("http://localhost:5000/edit/company", {
method: "POST",
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(function(response) {
if (response.status >= 400) {
throw new Error("Bad Response from server");
}
return response.json();
})
.then(function(data) {
console.log(data);
if (data === "success") {
// e.target.checked : !e.target.checked;
this.setState({ msg: "Company Edited", active: !e.target.checked });
}
})
.catch(function(err) {
console.log(err);
});
// this.setState({ });
}
You are passing two functions to the onClick and as far as I know (though I am not able to give a source for this or tell you why) react will only use the last value you give to props. This is why setting the state of cked probably did not work.
I would suggest giving it only 1 function like so:
onClick={
(e) => {
this.setState({ cked: !this.state.cked });
this.handleActivated(e, com.cid)
}
}
If you want to only execute the second one after the setState is done(since it is async), you should use the callback function of setState.
onClick={
(e) => {
this.setState({ cked: !this.state.cked }, () => {
this.handleActivated(e, com.cid)
});
}
}
I'm working on a project in AspNetCore with EntityFrameworkCore and i would like to use Ajax to get an object but my controller can't serialize this object correctly in Json, so my Ajax call trigger an error instead of a success event.
Here is my controller + test JsonConvert that return null.
[HttpGet]
public async Task<IActionResult> GetPackWithAllCards(int? packId)
{
if (packId == null)
{
return Json("An error has occured");
}
else
{
var pack = await _context.Packs
.Include(p => p.TagPacks)
.ThenInclude(tp => tp.Tag)
.Include(p => p.CardPacks)
.ThenInclude(cp => cp.Card)
.ThenInclude(c => c.FaceCards)
.ThenInclude(fc => fc.Face)
.ThenInclude(fc => fc.Template)
.Include(p => p.CardPacks)
.ThenInclude(cp => cp.Card.FaceCards)
.ThenInclude(fc => fc.Face.Image)
.Include(p => p.CardPacks)
.ThenInclude(cp => cp.Card.FaceCards)
.ThenInclude(fc => fc.Face.Sound)
.SingleOrDefaultAsync(m => m.PackId == packId);
//pack is correctly returned from database
if (pack == null)
{
return Json("An error has occured");
}
var a = JsonConvert.SerializeObject(pack);
return Ok(pack);
}
}
and my ajax call with typescript object:
var pack = new Pack(0, 0, 0, "", "", 0, 0, false, null, null);
$.ajax({
type: "GET",
url: "/pack/GetPackWithAllCards",
dataType: "text",
data: {packId},
async: false,
success: function (response) {
$.extend(pack, response);
alert("succes:"+response.packId);
},
error: function (response) {
$.extend(pack, response);
alert("error:" + response);
}
});
alert(pack);
return pack;
I hope someone could help me, i really don't find a solution to my problem.
I do this:
return new ContentResult
{
Content = JsonConvert.SerializeObject(data, Formatting.None, new JsonSerializerSettings {ReferenceLoopHandling = ReferenceLoopHandling.Ignore}),
ContentType = "application/json"
};
Are you getting the packId value in the controller? you may need to use:
data: {packId : packId},
i'm getting a list view json results and I would like to redirect to a different view and display the results according to my json
( I hope i'm clear) this what i'm did
<script type="text/javascript">
$(document).ready(function () {
$("#term").autocomplete({
source: function (request, response) {
$.ajax({
url: "Home/GetSubjectsName",
data: "{'term': '" + request.term + "' }",
dataType: 'json',
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
response($.map(data, function (item) {
return {
label: item.value,
value: item.value,
id: item.id,
}
var url = '#Url.Action("bla", "blaaaa")';
}))
}
});
},
minLength: 2,
});
});
my jsonlook like this :
public JsonResult GetSubjectsName(string term)
{
var results = db.subjects.Where(s => term == null ||
s.SubjectName.ToLower().Contains(term.ToLower())).Select(x => new
{ id = x.SubjectId, value = x.SubjectName }).Distinct().ToList();
return Json(results, JsonRequestBehavior.AllowGet);
}
and the action I would like to display the results is this (instead of partial view)
public ActionResult bla(string term)
{
IEnumerable serach = from sub in db.subjects.Where(t => t.SubjectName.Contains(term)).Distinct()
select new SearchResultsViewModel
{
Created = sub.Created,
Gender = sub.Gender,
OccupationDecription = sub.OccupationDecription,
Image = sub.Image,
SubjectName = sub.SubjectName
};
ViewBag.term = term;
return RedirectToAction("bla", "home", serach.ToList());
}
my View :
#model IEnumerable<MyProJect.ViewModels.SearchResultsViewModel>
foreach ....
what I need is to go to a different action and display the data
Here's some code that might help. Your post is still a bit unclear, so I'm filling in the missing pieces according to what you have described. I've made no attempt at designing the form layout.
Home/Index.cshtml:
#using( Html.BeginForm("bla") ) {
#Html.LabelFor(model => model.term)
#Html.EditorFor(model => model.term)
<button type="submit">Submit</button>
}
<script type="text/javascript">
jQuery(function ($) {
$("#term").autocomplete({ source: '#Url.Action("GetSubjectsName")', autoFocus: true, minLength: 2 });
});
</script>
Your autocomplete should be changed to:
public JsonResult GetSubjectsName(string term)
{
return Json(db.subjects
.Where(s => term == null ||
s.SubjectName.ToLower()
.Contains(term.ToLower()))
.OrderBy(x => x.SubjectName)
.Select(x => x.SubjectName)
.Distinct(), JsonRequestBehavior.AllowGet);
}
As far as I can tell, everything else should work as intended.