Updating a list with ajax and razor - ajax

I have a page in asp.net core razor, which is updating the database. I use ajax to go to the controller, the world is done, but I am not able to update the list that the ajax method returns.
This is my ajax method:
$.ajax(
{
url: "/Uploader/Update",
type: 'post',
data: {
Id: valor
},
success: function (data) {
$("#LaudosDocumentos").html(data);
}
})
Here is my Controller:
public async Task<IActionResult> Update(int Id)
{
ApplicationUser user = await _userManager.GetUserAsync(User);
if (!ModelState.IsValid)
{
return NotFound();
}
Laudos = _context.Laudos.Find(Id);
Laudos.Excluido = true;
Laudos.AlteracaoUsuId = user.Id;
_context.Attach(Laudos).State = EntityState.Modified;
await _context.SaveChangesAsync();
Id = Laudos.PessoaId;
LaudosDocumentos = await _context.Laudos.Where(m => m.PessoaId == Id && m.Excluido == false).ToListAsync();
return Json( new { LaudosDocumentos });
}
This is my page cshtml:
<div class="col-sm">
#if (Model.LaudosDocumentos.Count > 0)
{
<label class="control-label" style="margin-left:10px">
Arquivo(s) encontrado(s)
</label>
}
else
{
<label class="control-label" style="margin-left:10px">
Nenhum arquivo foi enviado para analise.
</label>
}
<div class="btn btn-default btn-file">
#foreach (var item in Model.LaudosDocumentos)
{
var ponto = item.Caminho.IndexOf(".");
var extensao = item.Caminho.Substring(ponto + 1);
if (extensao == "png" || extensao == "jpg" || extensao == "gif" || extensao == "jpeg")
{
<a class="example-image-link" href="/uploads/#Html.DisplayFor(modelItem => item.PessoaId)/#Html.DisplayFor(modelItem => item.Caminho)" data-lightbox="example-set" data-title="">
<img src="/uploads/#Html.DisplayFor(modelItem => item.PessoaId)/#Html.DisplayFor(modelItem => item.Caminho)" class="img-thumbnail" alt="Laudos" style="width:200px; height:200px;" />
</a>
<span style="font-size:23px; margin-left:10px;"> <i class="far fa-trash-alt" onclick="ExcluirArquivo(#Html.DisplayFor(modelItem => item.Id));"></i></span>
<span> <i class="far fa-trash-alt" onclick="ExcluirArquivo(#Html.DisplayFor(modelItem => item.Id));"></i></span>
}
}
</div>
</div>
I just need to update the list Model.LaudosDocumentos
but without having to pass the Id of a div.
I've tried to pass the item value in ajax but it also didn't work.

Json( new { LaudosDocumentos }) will return Json data , you should create your html markup and associated with Json value using Javascript , here is code sample .
If you don't want to create html in javscript manually , you can put the whole <div> to partial view , and use ajax to call server side function to query/load the partial view with passed model/value , and at last in success function of Ajax directly load the html using .html(result); . Here is coed sample .

Related

ajax post failed but controller & db data ok

im posting data to controller with partailview the controller receive valid data & store it in my DB but:
im getting ajax failed Msg.
im not getting a TempData displayed as expected ( i have one for results OK and else for error).
Im not sure where to put my finger on .
Index View
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
function SubmitREgNews() {
var data = {
userName: $("#name").val(),
UserMail: $("#email").val(),
TermsOk: $("#bOk").val(),
};
$.ajax({
type: 'POST',
url: "/NewsLetter/Create",
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: data,
success: function(result) {
alert('Successfully received Data ');
console.log(result);
},
error: function() {
alert('Failed to receive the Data');
console.log(JSON.stringify(error));
console.log('Failed ');
}
});
}
Partial view
#if (#TempData["ErrorMes"] != null)
{
#TempData["ErrorMes"]
}
#if (#TempData["regOk"] == null)
{
<div class="row">
<div class="col-md-4">
<form id="studenteForm" novalidate class="needs-validation">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="userName" class="control-label"></label>
<input asp-for="userName" class="form-control" id="name" required />
</div>
<div class="form-group">
<label asp-for="UserMail" class="control-label"></label>
<input asp-for="UserMail" type="email" class="form-control" id="email" /> </div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" id="bOk" asp-for="TermsOk" /> #Html.DisplayNameFor(model => model.TermsOk)
</label>
</div>
<div class="form-group">
<button type="button" class="btn btn-primary" onclick="SubmitREgNews();">Add </button>
</div>
</form>
</div>
</div>
</div>
}
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
controller
public IActionResult _RegNews()
{
return PartialView();
}
[HttpPost]
public async Task<IActionResult> Create([Bind("JoinId,userName,UserMail,TermsOk")] JoinNews joinNews )
{
var IsNewUser = await _context.joinNewsL.FirstOrDefaultAsync(a =>
a.UserMail.ToUpper() == (joinNews.UserMail.ToUpper()));
if ( ModelState.IsValid && IsNewUser==null)
{
joinNews.JoinId = Guid.NewGuid();
joinNews.JoinDate = DateTime.Now;
_context.Add(joinNews);
await _context.SaveChangesAsync();
TempData["regOk"] = "You are register";
return View("home/index");
}
else
{
TempData["ErrorMes"] = "You are allready register";
}
return PartialView("_RegNews", joinNews);
}
The reason you are getting ajax failed Msg may be that you are returning the wrong path "home/index". Paths in one controller that call a page in another controller should use "../home/index".
Also, Ajax doesn't change page elements. If you want to redirect to another page you can use Url.Action.
Like this:
Controller:
[HttpPost]
public async Task<IActionResult> Create([Bind("JoinId,userName,UserMail,TermsOk")] JoinNews joinNews)
{
var IsNewUser = await _context.joinNewsL.FirstOrDefaultAsync(a =>
a.UserMail.ToUpper() == (joinNews.UserMail.ToUpper()));
if (ModelState.IsValid && IsNewUser == null)
{
joinNews.JoinId = Guid.NewGuid();
joinNews.JoinDate = DateTime.Now;
_context.Add(joinNews);
await _context.SaveChangesAsync();
TempData["regOk"] = "You are register";
return Json(new { redirectUrlOne = Url.Action("Index", "Home")});
}
else
{
TempData["ErrorMes"] = "You are allready register";
return Json(new { redirectUrlTwo = Url.Action("_RegNews", "NewsLetter") });
}
}
And your ajax:
$.ajax({
type: 'POST',
url: "/NewsLetter/Create",
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: data,
success: function (result) {
alert('Successfully received Data ');
if (result.redirectUrlOne !== undefined) {
window.location.replace(result.redirectUrlOne);
} else {
window.location.replace(result.redirectUrlTwo);
}
console.log(result);
},
error: function (error) {
alert('Failed to receive the Data');
console.log(JSON.stringify(error));
console.log('Failed ');
}
});
If you don't want to use Url.Action, you can also do not use Ajax, using the Form Tag Helper to submit data is the same. You can check the details in this official document.

How to refresh only particular portion of page afte I upload Image file

So here I want to get the latest data from dbs after uploading a image. with reloading the whole page again. Instead I want only to refresh the image div to show the latest uploaded image. I guess we can use Ajax for this, but I don't have any expertise in ajax so anyone who can help will be glad.
Thank you :)
Here is my code :-----------
.cshtml file
#for (int i = 0; i < Model.DailyMenuProducts.Count; i++)
{
<li class="list-group-item">
<input asp-for="#Model.DailyMenuProducts[i].IsChecked" type="checkbox" />
<label asp-for="#Model.DailyMenuProducts[i].ProductId"> #Model.DailyMenuProducts[i].ProductName</label>
<input type="hidden" asp-for="#Model.DailyMenuProducts[i].ProductId"/>
<input type="hidden" asp-for="#Model.DailyMenuProducts[i].ProductName" asp-route-productId/>
#if(#Model.DailyMenuProducts[i].DisplayImage != null)
{
<div class="uploadFile float-end" id="div_#Model.DailyMenuProducts[i].ProductId">
<label class="file-label">
<img src="data:image/jpeg;base64,#Model.DailyMenuProducts[i].DisplayImage" width="80" height="80" style="border: 1px solid #000000; cursor:pointer;"/>
</label>
<input asp-for="#Model.DailyMenuProducts[i].ProductImage" asp-for-ProductId="#Model.DailyMenuProducts[i].ProductId" type="file" class="productImage" id="#Model.DailyMenuProducts[i].ProductId" style="visibility:none; display:none"/>
</div> }
else
{
<div class="uploadFile float-end" id="div_#Model.DailyMenuProducts[i].ProductId">
<a class="file-label btn btn-primary text-white" type="button">
#SharedLocalizer[CashlessCloudConstants.cacheKey_UploadImage]
</a>
<input asp-for="#Model.DailyMenuProducts[i].ProductImage" asp-for-ProductId="#Model.DailyMenuProducts[i].ProductId" type="file" class="productImage" id="#Model.DailyMenuProducts[i].ProductId" style="visibility:none; display:none"/>
</div>
}
</li>
}
.js file
$(".file-label").click(function () {
var parent = $(this).parent();
var target = $(parent).find(".productImage");
$(target).click();
});
$(".uploadFile").on('change', function () {
console.log('new file uploaded')
var imagefiles = event.target.files;
var id = event.target.id;
$(this).find(".imageViewer").attr("src", window.URL.createObjectURL(imagefiles[0]));
var formData = new FormData();
formData.append("productId", id);
formData.append("productImage", imagefiles[0]);
console.log(formData.getAll("productId"));
console.log(formData.getAll("productImage"));
console.log(imagefiles[0])
$.ajax({
url: "/DailyMenuPlanner/AddPhoto",
contentType: false,
processData: false,
data: formData,
method: "POST",
success: function (result) {
window.onbeforeunload = null;
location.reload();
}
});
});
.cs file [Controller Method for AddPhoto]
[HttpPost]
public async Task<IActionResult> AddPhoto([FromForm] DailySelectedProductViewModel dataModel)
{
var userSession = await _userSessionCache.GetUserSessionWithUserIdAsync();
if (dataModel == null)
{
return View("ProductSelection", dataModel);
}
var existing = await _productImageApiService.GetSingleProductImage(userSession.TenantId,dataModel.ProductId);
ProductImages productImage = new ProductImages();
HttpRequest request = HttpContext.Request;
IFormFile file = dataModel.ProductImage;
if (file.Length > 0)
{
using (var memoryStream = new MemoryStream())
{
await file.CopyToAsync(memoryStream);
byte[] imageAsArray = memoryStream.ToArray();
productImage.ProductImage = imageAsArray;
}
productImage.ProductId = dataModel.ProductId;
}
if (existing.Content != null)
{
await _productImageApiService.Delete(userSession.TenantId,dataModel.ProductId);
var createProductPhoto = await _productImageApiService.Create(userSession.TenantId, productImage);
}
else
{
var createProductPhoto = await _productImageApiService.Create(userSession.TenantId, productImage);
}
return Ok();
}

ajax form request from a while - confuse variable

I want to send a form with a button from a while, but I have a problem. If post the button, the form confuse the variable. E.g: i post the button with id 1, and the script get the variable from the last input.
Code:
index:
<?php
$res = getProdus();
foreach($res as $row) { ?>
<form action="addtocart.php" method="POST">
<div class="col-12 col-sm-6 col-md-4 single_gallery_item women wow fadeInUpBig" data-wow-delay="0.2s">
<div class="product-img">
<img src="img/product-img/product-1.jpg" alt="">
<div class="product-quicview">
<i class="ti-plus"></i>
</div>
</div>
<div class="product-description">
<h4 class="product-price">$39.90</h4>
<p>Jeans midi cocktail dress</p>
<input type="hidden" name="addtcart" value="<?=$row['ID'];?>">
<button type="submit" class="add-to-cart-btn">ADD TO CART</button>
</div>
</div>
</form>
<?php } ?>
the ajax request:
$(document).ready(function() {
$('form').submit(function(event) {
var formData = {
'addtcart' : $('input[name=addtcart]').val()
};
$.ajax({
type : 'POST',
url : 'addtocart.php',
data : formData,
dataType : 'json',
encode : true
})
.done(function(data) {
console.log(data);
});
event.preventDefault();
});
});
and the addtocart.php
<?php
include("includes/functions.php");
session_start();
$errors = array(); // array to hold validation errors
$data = array(); // array to pass back data
if (empty($_POST['addtcart']))
$errors['addtcart'] = 'Este necesar produsul id-ului.';
if ( ! empty($errors)) {
$data['success'] = false;
$data['errors'] = $errors;
} else {
$ok = AddToCart(filtrare($_POST['addtcart']), getSpec("username", "users", "email", $_SESSION['magazin-user']));
if($ok == 1) {
$data['success'] = true;
$data['message'] = 'Success!';
} else {
$data['success'] = false;
$errors['mysqli'] = "Nu s-a realizat bine query-ul.";
$data['errors'] = $errors;
}
}
echo json_encode($data);
?>
Replace your button code with this
<button type="submit" value="<?=$row['ID'];?>" class="add-to-cart-btn">ADD TO CART</button>
and after that replace you
make changes to your script code
$(".add-to-cart-btn").click(function() {
var formData = {
'addtcart' : $(this).val()
};
.
.
.
and your rest of the code.

Spring MVC and bootstrap modal form : how to create server-side validation for it?

I'm newbie at spring and front-end at all.
I have (not mine) an old front-end code to show modal form over some page :
modal form is:
<div id="myModalForm" class="modal inmodal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog ">
<div class="modal-content animated fadeIn">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span
aria-hidden="true">×</span><span class="sr-only"></span></button>
<h4 class="modal-title"><spring:message code="entity.modal.title"/></h4>
</div>
<div id="modalContent" class="modal-body">
<form id="createForm" name="createForm" class="" action="/entity/create"
method="post" enctype="multipart/form-data">
...
</form>
</div>
</div>
</div>
</div>
form is shown from java scripts. Button that invokes form is:
<script>
$(document).ready(function () {
$('#tbl').DataTable({
responsive: true,
dom: 'l<"toolbar">frtip',
initComplete: function () {
$("div.toolbar")
.html('<button id="new_entity_btn" type="button" class = "btn btn-white" onclick="openCreateWindow()" ><spring:message
code="entity.table.create.btn"/> </button>');
}
});
/*activate tooltips*/
$(function () {
$('[data-toggle="popover"]').popover();
});
});
</script>
and onclick for button is:
<script>
function openCreateWindow() {
$('#myModalForm').modal('show');
}
</script>
Now as you can see #myModalForm is not a Spring view form as it doesn't generate even get-request to be shown. It just appears over existing page in modal mode. Now the question is how to create server-side validation for it? I've tried next:
1) refactor it to spring mvc form i.e. via
<form:form ... />
tag with attribute
ModelAttribute='MyFormAttribute'. But i have no idea how to create back-end object for MyFormAttribute as appearance of form doesn't generate get-request. And idea was to have on post method of controller something like:
#RequestMapping(value = {"/entity/create"}, method = RequestMethod.POST)
String createNewEntity(
#ModelAttribute("MyFormAttribute") MyEntity entity,
BindingResult bindingResult,
Model model)
2) Trying to change post method of controller so that it might return error. But there is no way to create bindingResult parameter in case if form is not mvc one
3) Trying to validate via jQuery.validate i.e. smth. like :
<script>
/*form validation*/
$().ready(function () {
$("#createForm").validate({
rules: {
Field1: {
remote: function () {
var r = {
url: '/validateEntityField1',
type: "POST"
};
return r;
}
},
Field2: {
remote: function () {
var r = {
url: '/validateEntityField2',
type: "POST"
};
return r;
}
}
...
},
errorElement: "em",
highlight: function (element, errorClass, validClass) {
$(element).fadeOut(function () {
$(element).fadeIn();
});
$(element).addClass(errorClass).removeClass(validClass)
},
unhighlight: function (element, errorClass, validClass) {
$(element).removeClass(errorClass).addClass(validClass)
}
})
;
});
</script>
But it looks rather ugly as i should validate every field separately on its own end point and. Besides form has file input so i should send it twice or smth.
So, how could i achieve next issue:
leave modal form over existing page
validate it on server side. It would be nice to make validation against whole entity.
Answering on my commented question. Not the exact code you are looking but will give you an idea. Though it depends on individual choice, in controller you can use ValidationUtils as shown below. Here you can map your error messages and json response which later on you want on your front-end:
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public #ResponseBody JsonResponse addUser(#ModelAttribute("user") User user, BindingResult result, Errors errors, Model model) {
JsonResponse response = new JsonResponse();
ValidationUtils.rejectIfEmptyOrWhitespace(result, "firstname", "Firstname is required. It can not be empty.");
if (user.getFirstname().length() < 4 || user.getFirstname().length() > 32) {
errors.rejectValue("firstname", "Firstname must be between 4 and 32 characters.");
}
ValidationUtils.rejectIfEmptyOrWhitespace(result, "lastname", "Lastname is required. It can not be empty.");
if (user.getLastname().length() < 4 || user.getLastname().length() > 32) {
errors.rejectValue("lastname", "Lastname must be between 4 and 32 characters.");
}
if (!result.hasErrors()) {
userList.add(user);
response.setStatus("SUCCESS");
response.setResult(userList);
} else {
response.setStatus("FAIL");
response.setResult(result.getAllErrors());
}
return response;
}
And I picked the sample for Bootstrap Modal from here:
https://www.w3schools.com/bootstrap4/bootstrap_modal.asp
Somewhere in your html:
<!-- Modal body -->
<div class="modal-body">
<div class="form-group">
<label class="col-form-label" for="username">Enter your First Name</label>
<i class="fas fa-users"></i>
<input type="text" id="firstname" class="form-control">
</div>
....
....
</div>
Put up (similar to this) in your ajax:
if (response.status == "SUCCESS") {
userInfo = "<ol>";
for (i = 0; i < response.result.length; i++) {
userInfo += "<br><li><b>Firstname</b> : "
+ response.result[i].firstname
+ response.result[i].lastname;
}
And
errorInfo = "";
for (i = 0; i < response.result.length; i++) {
errorInfo += "<br>" + (i + 1) + ". "
+ response.result[i].code;
}
$('#error').html(
"<b>Errors found during validation : </b>"
+ errorInfo);
I created a small piece of code for this. You can take a look here on GitHub.

Umbraco BlogComment Create Ajax

Hello im trying to post my blog comments the function works. but the whole site refreshes inside the div, i tried playing around with the partialview in the controller but im not sure what to do can anybody here point me in the right directtion, i want div to refresh with ajax request not the whole site intro the div.
<!-- Blog Comments -->
<!-- Comments Form -->
<div class="well">
<h4>Leave a Comment:</h4>
#if (Members.GetCurrentLoginStatus().IsLoggedIn)
{
using (Html.BeginUmbracoForm("CreateComment", "CommentSurface", FormMethod.Post, new { #id = "comment-form" }))
{
// use this where every display profile image is needed
var user = User.Identity.Name;
var imgUrl = Url.Content("~/media/profileimage/" + user.Replace(".", "") + ".png");
<input name="CommentOwner" type="text" value="#Members.GetCurrentMember().Name" class="form-control hidden" readonly="readonly" />
<input name="ownerid" type="text" value="#Members.GetCurrentMember().Id" class="form-control hidden" readonly="readonly" />
<div class="form-group">
<textarea name="Message" rows="3" placeholder="Type your message here" class="form-control"></textarea>
</div>
<input name="profileimage" type="text" value="#imgUrl" class="hidden" readonly="readonly" />
<button type="submit" class="btn btn-primary">Submit</button>
}
}
else
{
<p> You are not logged in Register here</p>
}
</div>
<hr>
<!-- Posted Comments -->
<div class="blog-comments">
#Html.Partial("_BlogComments")
</div>
<!-- Comment -->
#section scripts {
<script>
$(function () {
// Find the form with id='well-form'
$('#comment-form').submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (data) {
$(".blog-comments").html(data);
},
error: function (result) {
alert('Comment was not successful!');
}
});
// return false to cancel the form post
// since javascript will perform it with ajax
return false;
});
});
</script>
}
</div>
SurfaceController:
public class CommentSurfaceController : SurfaceController
{
[HttpPost, ValidateInput(false)]
public ActionResult CreateComment(CommentViewModel model)
//public PartialViewResult CreateComment(CommentViewModel model)
{
if (!ModelState.IsValid)
{
return CurrentUmbracoPage();
}
var contentService = Services.ContentService;
var newContent = contentService.CreateContent(DateTime.Now.ToShortDateString() + " " + model.CommentOwner, UmbracoContext.PageId.Value, "BlogComment");
newContent.SetValue("CommentOwner", model.CommentOwner);
newContent.SetValue("Message", model.Message);
newContent.SetValue("profileimage", model.profileimage);
newContent.SetValue("ownerid", model.ownerid);
//Change .Save if u want to allow the content before publish
contentService.SaveAndPublishWithStatus(newContent);
return RedirectToCurrentUmbracoPage();
//return PartialView("BlogComments", model);
}
public ActionResult DeleteComment(int commentid)
{
var service = ApplicationContext.Current.Services.ContentService;
var content = service.GetById(commentid);
service.Delete(content);
return RedirectToCurrentUmbracoPage();
}
}
Partial View:
#foreach (var item in Model.Content.Children().OrderByDescending(m => m.CreateDate))
{
<div class="media">
<a class="pull-left" href="#">
<img class="media-object" width="64" src="#item.GetPropertyValue("profileimage")" alt="profile image">
</a>
<div class="media-body">
<h4 class="media-heading">
#item.GetPropertyValue("CommentOwner")
<small>#item.CreateDate</small>
</h4>
#item.GetPropertyValue("Message")
</div>
#item.Id
</div>
if (Members.GetCurrentLoginStatus().IsLoggedIn)
{
if (#Members.GetCurrentMember().Id.ToString() == item.GetPropertyValue("ownerid").ToString())
{
#Html.ActionLink("Delete", "DeleteComment", "CommentSurface", new { commentid = item.Id }, null)
}
else
{
#*<p> not ur comment</p>*#
}
}
else
{
//blank cant delete comment if not logged in
}
}
The problem is that UmbracoSurfaceController is loosing his context if you are not rendering the complete page.
If you work with ajax, you should not render out html and post this back. Only POST the data and update your layout in javascript when you get a 200 (ok) back from the server.
To do so, use the UmbracoApiController. This is a WebApi controller allowing you to send back json (or xml) serialized data.
More information about the UmbracoApiController can be found in the documentation.

Resources