Hi everyone i'm new to spring MVC so i have little idea about the framework. All I'm trying to do is refresh a div in my view with items filtered by a hibernate query, which prints correctly to standard out.
For some reason I'm not aware of I get a 500; Internal server error when i try a get request via ajax.
I changed the return type in the controller, my original idea was to use the default index controller with an optional parameter.
View:
<div id="itemListContainer">
<c:if test="${!empty items}">
<c:forEach items="${items}" var="item">
<c:url value="/showImage.htm" var="url">
<c:param name="id" value="${item.id}" />
</c:url>
<div id="${item.id}" class="col-lg-2 col-md-3 col-xs-6 thumb">
<img class="img-responsive" src="${url}" alt="${item.name}">
</div>
<input id="name_${item.id}" type="hidden" value="${item.name}">
<input id="name_${item.id}" type="hidden" value="${item.review}">
</c:forEach>
</c:if>
<c:if test="${!empty itemList}">
<h1>Nothing found</h1>
</c:if>
</div>
JS File
function filterItems(value) {
$("#itemListContainer").empty();
$.ajax({
method: "GET",
//dataType: "json",
url: "filterItems.htm",
data: {
type: value
},
success: function (data) {
if (data) {
$("#itemListContainer").html(data);
} else {
console.log(xhr.responseText);
alert("failure");
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("Status: " + textStatus); alert("Error: " + errorThrown);
}
});
}
Controller:
#RequestMapping(value = "/filterItems", method = RequestMethod.GET)
public #ResponseBody List<Item> filterItems(#RequestParam(value = "type", required = false) String type) {
List<Item> items = new ArrayList<Item>();
try {
items = itemDao.getItems(type);
} catch (Exception e) {
e.printStackTrace();
}
return items;
}
Any help will be greatly appreciated. Thanks in advance!!
Once again, when it comes my little experience with hibernate, the error has nothing to do with Javascript, controller o DAO but with entity mapping.
My Item entity had an association with a User entity, and had to specify between lazy and eager loading of the association. In my case it was solved by adding lazy="true" to my xml file.
Related
Below is the sample code, i am calling this code on button click event. My question is, can i validate my viewmodel object before making ajax call? i can see model errors in java script, not sure how to check.
My viewmodel class properties has Data Annotation Validator Attributes. I don't want make ajax call if the viewmodel is not valid, want to check (ModelState.IsValid) in java script code, before making ajax call.
Any help, would be greatly appreciated.
$(function () {
$("#btnGet").click(function () {
var viewModelobject = {};
viewModelobject.Name = $("#txtName").val();
$.ajax({
type: "POST",
url: "/Home/AjaxMethod",
data: viewModelobject,
contentType: "application/json",
dataType: "json",
success: function (response) {
alert("Hello")
}
});
});
}
ModelState.IsValid is server side code.Browser has no idea about what it is,so you could not validate ModelState in client side. You can use Jquery Validation at client side.
Here is a working demo:
1.Model:
public class UserModel
{
[Required(ErrorMessage = "The Name field is required.")]
[Display(Name = "Name")]
public string Name { get; set; }
}
2.View(Index.cshtml):
#model UserModel
<form id="frmContact">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" id="txtName" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<button type="submit" class="btn btn-secondary" id="btnGet">Click</button>
</div>
</form>
#section Scripts
{
#*you could also add this partial view*#
#*#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}*#
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.15.1/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"></script>
<script>
$(function () {
$('#btnGet').click(function () {
if ($("#frmContact").valid()) {
$('#frmContact').submit();
}
else {
return false;
}
});
$("#frmContact").on("submit", function (event) {
event.preventDefault();
var viewModelobject = {};
viewModelobject.Name = $("#txtName").val();
$.ajax({
type: "POST",
url: "/Home/AjaxMethod",
data: JSON.stringify(viewModelobject),
contentType: "application/json",
dataType: "json",
success: function (response) {
alert("Hello")
}
});
});
})
</script>
}
3.Controller:
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public IActionResult AjaxMethod([FromBody]UserModel user)
{
//do your stuff...
return Json(user);
}
}
Result:
Please use jQuery form validation as shown below inside the button click callback:
var form = $('form[name="' + formName + '"]');
form.validate();
if (form.valid()) {
//Do something if the form is valid
}
else {
//Show validation error messages if the form is in-valid
}
I'm using spring boot MVC, and have a part that I make an ajax request to update a collection of products for merchandise shipment, but when I post it is displaying json on the screen instead of updating the fragment:
<th:block th:if="${expedicao.tipoRegistro eq 'A' or expedicao.tipoRegistro eq 'X'}">
<form action="#" th:action="#{/expedicao/buscaprod}" method="post"
name="formBusca">
<input type="hidden" th:name="${_csrf.parameterName}"
th:value="${_csrf.token}" /> <label th:text="Ean13">Ean13</label>
<input type="radio" name="tipoCod" id="tipoCod" value="ean13" /> <label
th:text="Dun14">Dun14</label> <input type="radio" name="tipoCod"
id="tipoCod" value="dun14" /> <input type="text"
name="FieldCodigo" class="form-control" placeholder="Codigo Barras"
id="FieldCodigo" value="" autofocus="autofocus" required="required" />
<input type="hidden" name="id_expedicao" id="id_expedicao"
th:value="${expedicao.id}" />
<button type="submit" value="Buscar">Buscar</button>
</form>
</th:block>
<div th:fragment="info-success" xmlns:th="http://www.thymeleaf.org" th:remove="tag">
<div class="modal-body row" id="coleta">
<div th:replace="expedicao/coleta::coleta"></div>
</div>
</div>
</div>
this is my ajax
<th:block layout:fragment="scripts">
<script th:inline="javascript">
/*<![CDATA[*/
$(function() {
$.ajaxSetup({
headers : {
'X-CSRF-Token' : $('meta[name=_token]').attr('content')
}
});
$('form#formBusca').submit(
function(e) {
e.preventDefault();
$.ajax({
type : "POST",
contentType : "application/json",
url : 'expedicao/buscaprod',
data : $('form#formBusca').serialize(),
dataType : 'json',
success : function(result) {
if(result.status == "Done"){
carregarColeta(result.data.id);
if (result.data.situacao == 'B'
|| result.data.situacao == 'C') {
$('form#formBusca').remove();
}
},
error : function(jqXHR, textStatus, errorThrown) {
console.log(JSON.stringify(jqXHR));
console.log("AJAX error:" + textStatus + ' : '
+ errorThrown);
}
});
$('input[name=FieldCodigo]').val('');
});
});
function carregarColeta(idexpedicao) {
$.ajax({
method : 'POST',
url : 'expedicao/detalhe',
data : {
'id_expedicao' : idexpedicao
},
success : function(retorno) {
$('#coleta').empty().html(retorno);
},
error : function(jqXHR, textStatus, errorThrown) {
console.log(JSON.stringify(jqXHR));
console.log("AJAX error:" + textStatus + ' : '
+ errorThrown);
}
});
}
when a execute the post method it go to my controller execute the logic and return the json of the object updated, and instead of update the fragment calling the JS function carregaExpedicao.. its dislpay the json on the screen, and change the url
this is my controller
#Controller
public class ExpedicaoController {
#RequestMapping(value = "/expedicao/buscaprod", method = RequestMethod.POST)
#ResponseBody
public Response updateProdutoColetado(
#RequestParam(name = "id_expedicao") String id_expedicao,
#RequestParam(name = "FieldCodigo") String FieldCodigo,
Model model, HttpSession session) {
//Minhas regras
model.addAttribute("expedicao", expedAndamento);
return new Response("Done", expedAndamento);
}
#RequestMapping(value = "/expedicao/detalhe")
public String detalhe(#RequestParam(name = "id_expedicao") String id_expedicao, Model model, HttpSession session) {
model.addAttribute("expedicao", expedAndamento);
return "expedicao/coleta";
}
}
Fixed:
error 1 => id on the form
error 2 => missing csrf param on ajax
I am trying to send some data from a modal dialog to my controller with Ajax. But my modelfields are always null, but I enter my actionmethod in the controller.
This is a shortend version of my cshtml-file.
#model anmespace.MyModel
<form method="post" id="formID">
...
<div class="row">
<div class="col-md-5">#Resource.GetResource("MyModal", "Firstname")</div>
<div class="col-md-7"><input type="text" class="form-control" id="firstname" value="#Html.DisplayFor(model => model.FirstName)"></div>
</div>
...
<input type="submit" class="btn btn-primary" value="Submit" />
</form>
<script>
$("#formID").on("submit", function (event) {
var $this = $(this);
var frmValues = $this.serialize();
$.ajax({
cache: false,
async: true,
type: "POST",
url: "#Url.Action("ActionName", "Controller")",
data: frmValues,
success: function (data) {
alert(data);
}
});
});
</script>
Sorry MVC/Ajax are really new for me.
If you want to bind the form data to model then, the names of HTML elements should match with Model properties.
Note: name attribute value of html input field should match to the property of a model.
When you use form and submit button then it will try to reload the page by posting data to the server. You need to prevent this action. You can do this by returning false on onSubmit event in the Form element.
When you use jquery, do not forget to keep the ajax call/events inside the $(document).ready(function(){}) function.
I have written a simple code which takes First Name as input and makes an ajax call on clicking on submit button.
Html & Jquery Code:
<script>
$(document).ready(function() {
$("#formID").on("submit", function(event) {
var $this = $(this);
var frmValues = $this.serialize();
$.ajax({
cache: false,
async: true,
type: "POST",
url: "#Url.Action("PostData", "Home")",
data: frmValues,
success: function(data) {
alert(data.FirstName);
}
});
});
});
</script>
<div>
<form method="post" id="formID" onsubmit="return false;">
<input id="FirstName" name="FirstName"/>
<input type="submit" value="submit" />
</form>
</div>
My Model :
public class Person
{
public string FirstName { get; set; }
}
Action Method:
public ActionResult PostData(Person person)
{
return Json(new { Success = true, FirstName = person.FirstName });
}
Output:
I am trying to achieve the same result as mentioned by the OP in this post However when I try to render partial view by checking if it was an AJAX request in my Index action, its evaluating to false.
My Index View:
#using (Ajax.BeginForm("Index", "Home",
new AjaxOptions()
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "restaurantList"
}))
{
<input type="search" name="searchTerm" />
<input type="submit" value="Search By Name" />
}
#Html.Partial("_Restaurant",Model)
My Partial View:
<div id="restaurantList" style="border:2px dotted red; padding-left:2em; margin-top:4px;">
#foreach (var item in Model)
{
<div>
<h4>#item.Name</h4>
<div>#item.City, #item.Country</div>
<div>#item.CountOfReviews</div>
<hr />
</div>
}
</div>
My Index Action:
public ActionResult Index(string searchTerm = null)
{
var model = ...//Building model object here
if (Request.IsAjaxRequest())
{
return PartialView("_Restaurant", model);
}
return View(model);
I would prefer not to dive into use of any jQuery or javascript as I am in the process of learning ASP.NET MVC, and would want to know why the approach I took is not working? The second answer by Dennis, in the post that I referenced also suggested similar approach.
Could someone kindly tell me what I am doing wrong?
Thanks
This is just an example how you can load view from AJAX without page refresh, it may help you.
It send text value to controller by ajax call and load that value in other view which replace main view, if you don't want to replace main view then you can take other div instead same div to load content.
Controller:
public ActionResult Index()
{
return View();
}
[HttpPost]
public PartialViewResult TestAjax(string Name)
{
ViewBag.Name = Name;
return PartialView();
}
Index.cshtml:
<input type="button" id="btnSearch" class="btn btn-warning" style="height:35px;width:120px" value="Search"/>
<label>Name:</label><input type="text" id="txtName" name="txtName" />
<script>
$('#btnSearch').click(function () {
$.ajax({
url: '#Url.Action("TestAjax", "Home")',
data: { Name: $("#txtName").val() },
type: 'POST',
success: function (data) {
$("#divContent").html(data);
}
});
});
</script>
TestAjax.cshtml:
#ViewBag.Name
As #StephenMuecke pointed out in his comments, the libraries not being loaded correctly was the problem. While creating a new bundle of all libraries and adding it in the BundkeConfig.cs I had missed ~/Scripts/jquery.unobtrusive-ajax.js*. Got it working now.
I have a form submit with an AJAX post. It works fine.
But when I delete the item by clicking the delete link, I have an issue, a get request not post.
But from my javascript function, you can see I use jQuery css selctor to detect the link clicked or not, so I am confused.
Here is my code
My controller:
public class SessionsController : Controller
{
private SessionRepository _repository;
public SessionsController() : this(new SessionRepository()) { }
public SessionsController(SessionRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
var sessions = _repository.FindAll();
//for ajax requests, we simply need to render the partial
if (Request.IsAjaxRequest())
return PartialView("_sessionList2", sessions);
//return View("_sessionList", sessions);
return View(sessions);
}
[HttpPost]
public ActionResult Add(Session session)
{
_repository.SaveSession(session);
if (Request.IsAjaxRequest())
return Index();
return RedirectToAction("index");
}
[HttpPost]
public ActionResult Remove(Guid session_id)
{
_repository.RemoveSession(session_id);
return RedirectToAction("index");
}
}
The session view:
#model IEnumerable<MyMVCDemo.Models.Session>
<h2>Hijax Technique</h2>
<div id="session-list">
#{Html.RenderPartial("_sessionList2");}
</div>
<p>
</p>
#using (Html.BeginForm("add", "sessions", FormMethod.Post, new { #class = "hijax" }))
{
<fieldset>
<legend>Propose new session</legend>
<label for="title">Title</label>
<input type="text" name="title" />
<label for="description">Description</label>
<textarea name="description" rows="3" cols="30"></textarea>
<label for="level">Level</label>
<select name="level">
<option selected="selected" value="100">100</option>
<option value="200">200</option>
<option value="300">300</option>
<option value="400">400</option>
</select>
<br />
<input type="submit" value="Add" />
<span id="indicator" style="display:none"><img src="../../content/load.gif" alt="loading..." /></span>
</fieldset>
}
<label>
<input type="checkbox" id="use_ajax" />
Use Ajax?
</label>
<script src="../../Scripts/Common.js" type="text/javascript"></script>
My Partial View:
#model IEnumerable<MyMVCDemo.Models.Session>
<table id="sessions">
<tr>
<th>Title</th>
<th>Description</th>
<th>Level</th>
<th></th>
</tr>
#if(Model.Count() == 0) {
<tr>
<td colspan="4" align="center">There are no sessions. Add one below!</td>
</tr>
}
#foreach (var session in Model)
{
<tr>
<td>#session.Title</td>
<td>#session.Description</td>
<td>session.Level</td>
<td>
#Html.ActionLink("remove", "remove", new { session_id = session.Id }, new { #class = "delete" })
</td>
</tr>
}
This is my javascript which call the ajax post:
$('.delete').click(function () {
if (confirm('Are you sure you want to delete this item?')) {
$.ajax({
url: this.href,
type: 'POST',
success: function (result) {
$("#session-list").html(result);
}
});
return false;
}
return false;
});
$("form.hijax").submit(function (event) {
if ($("#use_ajax")[0].checked == false)
return;
event.preventDefault(); //prevent the actual form post
hijack(this, update_sessions, "html");
});
function hijack(form, callback, format) {
$("#indicator").show();
$.ajax({
url: form.action,
type: form.method,
dataType: format,
data: $(form).serialize(),
completed: $("#indicator").hide(),
success: callback
});
}
function update_sessions(result) {
//clear the form
$("form.hijax")[0].reset();
//update the table with the resulting HTML from the server
$("#session-list").html(result);
$("#message").hide().html("session added")
.fadeIn('slow', function () {
var e = this;
setTimeout(function () { $(e).fadeOut('slow'); }, 2000);
});
}
It looks to me like you do not rebind the click event after you update the partial.
What happends is that you replace the DOM(which the events are bound to) when you make the ajax call. So after you update post the form all your events are gone.
In jquery there is a live event that would help you here.
The code below is not tested some there might be some problems with it but it should give you an idea.
var sessionList = $('#session-list');
$('.delete', sessionList).live('click', function () {
if (confirm('Are you sure you want to delete this item?')) {
$.ajax({
url: this.href,
type: 'POST',
success: function (result) {
sessionList.html(result);
}
});
return false;
}
return false;
});
The selector $('.delete', sessionList) is to give the live function a context so it doesn't bubble events all the way to the top.