Reputation: 1035
I have an inventory application in a layout like this:
<body>
<div class="container" style="width: 100%">
<div id="header"> blahblahblah </div>
<div class="row">
<div id="rendermenu" class="col-sm-2">
@Html.Action("Menu", "Nav")
</div>
<div id="renderbody" class="col-sm-10">
@RenderBody()
</div>
</div>
</div>
In the Home
controller there is an action method that filters the repository sent to the view:
public ActionResult Index(string categoria, string marca)
{
InventarioViewModel viewModel = new InventarioViewModel
{
Inventario = repository.GetInventario()
.Where(i => (categoria == null || i.Item.Categoria == categoria)
&& (marca == null || i.Item.Marca == marca))
.OrderBy(i => i.Qta > 0)
.ThenBy(i => i.Item.Categoria)
.ThenBy(i => i.Item.Marca)
.ThenBy(i => i.Item.Modello).ToList(),
CategoriaCorrente = categoria,
MarcaCorrente = marca
};
return View(viewModel);
}
It works fine, but only by typing the desired route in the browser. So I started writing a filter by putting a <select>
element that presents the user the items categories, then binding an AJAX call to its change
event. This is the markup for the menu view:
@using Magazzino.Domain.Infrastructure
@using Magazzino.Domain.Entities
@model List<Item>
@{ IEnumerable<Item> items = Model.DistinctBy(x => x.Categoria); }
<div class="text-center">Filtra per:</div>
<hr />
<div class="text-center">Categoria</div>
<select class="form-control lista-categorie" id="lista-categorie" data-action-url="@Url.Action("Index", "Home")" name="categoria">
<option value>-- seleziona --</option>
@foreach (Item item in items)
{
<option value="@item.Categoria">@item.Categoria</option>
}
</select>
This is the AJAX call, put inside the usual $(document).ready(...):
$('#lista-categorie').on('change', function () {
var e = $(this)[0];
if (e.selectedIndex > 0) {
var ajaxRequest = $.ajax({
url: "/",
type: "get",
data: {
categoria: e.options[e.selectedIndex].value,
marca: null
}
})
ajaxRequest.done(function (response) {
$('#renderbody').html(response);
});
}
});
I also changed part of the controller where the view is rendered:
if (Request.IsAjaxRequest())
{
return PartialView(viewModel);
}
else
{
return View(viewModel);
}
but I get just an empty string. If try to get the full view, I see that the response has the whole page (layout and menu) BUT the Index view:
// previous markups from layout and menu
<div id="renderbody" class="col-sm-10">
</div>
</div>
</div>
// other markups
I'm sure the Index action method is triggered because I put a breakpoint. Though, the moment I change the AJAX call itself this way, it works fine:
var ajaxRequest = $.ajax({
url: "/" + e.options[e.selectedIndex].value,
type: "get"
})
but I don't really like this workaround, I'd like to have a more plain, efficient way of passing data to the controller.
How can I change this behaviour?
Upvotes: 0
Views: 514
Reputation: 382
$('#lista-categorie').on('change',method_attached_to_event);
function method_attached_to_event(){
var e = $(this)[0];
if (e.selectedIndex > 0) {
var url = '/';
var obj = {};
obj.categoria= e.options[e.selectedIndex].value;
$.ajax({
url:url,
method:'POST',
data:obj,
success:success,
error:error
});
}else{
// Do something else
}
}
function success(data,status,jqxhr){
console.log(data);
}
function error( jqxhr, status, error ){
console.log(status);
console.log(error);
console.log(jqxhr);
}
Upvotes: 0
Reputation: 1035
TOTALLY my bad: I re-edited the question because when I said "I'm sure the ViewModel get populated", it was true-ish. I only checked that the action method was triggered.
I have now checked the ViewModel and found the problem: I didn't take into account that the "null" value sent by the AJAX call isn't actually null
, but an empty string. I have changed the LINQ expression accordingly and it works
InventarioViewModel viewModel = new InventarioViewModel
{
Inventario = repository.GetInventario()
.Where(i => (string.IsNullOrEmpty(categoria) || i.Item.Categoria == categoria)
&& (string.IsNullOrEmpty(marca) || i.Item.Marca == marca))
.OrderBy(i => i.Qta > 0)
.ThenBy(i => i.Item.Categoria)
.ThenBy(i => i.Item.Marca)
.ThenBy(i => i.Item.Modello).ToList(),
CategoriaCorrente = categoria,
MarcaCorrente = marca
};
Despite being a trivial bug (and an incredibly embarassing moment), I'd like to answer my own question and keep it for those who might face the same problem.
Cheers.
Upvotes: 1