views:

344

answers:

4

I've never used AJAX and am, quite frankly, not much versed in JS either.

I have a page (Product Browser) that has the following breakdown:

  1. Navigation (First, Prev, 1, 2, 3 Next, Last) - full post back
  2. Items per Page drop down - I want to AJAX this
  3. Left Column - Filters - I want to AJAX this
  4. Product Display area - displays products based on 1, 2 & 3 above

I am starting with Item #2 and am trying to figure out how to change item 4 based off of the OnChange event for the drop down. I am at a loss as to where. or how, to start. Should it be AJAX? JQuery? A combination of both? And remember - it is in a MVC based app.

TIA

A: 

You can try this simple demo from my blog

Jarrett Meyer
+2  A: 

AJAX is just a request pulling information from a page without refreshing the browser. You can use ASP.NET AJAX or JQuery's AJAX and you should get the same results.

And JQuery is just a library to select and manipulate the DOM. JQuery has a few AJAX functions you can use as well but JQuery can be used for much much more.

I don't know how ASP's version works exactly but AJAX is just a page request.

Ólafur Waage
A: 

I would definately check out jQuery and not bother with MS's ajax implementation. For the things you want, you can check out jQuery's docs for $post for example or ajax/load functions.

You can either add events to the controls on your page, like the carpets / area rugs radio buttons, or add that event to the submit button and then make a call to the products controller to retrieve a partial view that loads into the products div.

Morph
+2  A: 

The answer to your question is definitely, "yes".

I've got one in front of me right now, so I'll try to abstract it out.

First, create a controller action that returns a JsonResult (rather than ActionResult). Other than its return type it's just like any other action, so you can send parameters, etc. The only thing that's really different is that you're going to return a JsonResult() object, setting its Data property and any other properties that you may need. Mine looks something like this (very pseudo-codish...):

public JsonResult GetList(int parentId)
{
  var results = dataRepository.GetById(parentId);

  return new JsonResult()
  {
    Data = results.ToArray();
  };
}

Now, in your view, create a script that looks something like this. Note that this is jQuery syntax, so it may look a bit unusual if you're not familiar with it.

<script language="javascript" type="text/javascript">
// When the document is ready, start firing our AJAX
$(document).ready(function() {
  // Bind a function to the "change" event of our drop-down list
  $("#dropDownId").bind("change", function(e) {
    updateList();
  });
}

var retrieveData = function(path, parentId, fnHandleCallback) {
  // Use the getJSON method to call our JsonResult action
  $.getJSON(path, { parentId: parentId }, function(data) {
    fnHandleCallback(data);
  });
};

// The path parameter is our JSON controller action
function updateList() {
  retrieveData("/Controller/GetList", $("#dropDownId").val(), handleResponse);
}

function handleResponse(data) {
  // Ok, now we have the JSON data, we need to do something with it.  I'm adding it to another dropdown.
  $("#otherDropDownId > option").remove();

  for (d in data)
  {
    var item = data[d];

    $("#otherDropDownId").append("<option value=\"" + item.Value + "\">" + item.Text + "</option>");
  }
}
</script>

<%= Html.DropDownList("dropDownId", new SelectList(new List<SelectListItem>())) %>
<%= Html.DropDownList("otherDropDownId", new SelectList(new List<SelectListItem>())) %>

This is all very much off the top of my head, so let me know if something needs to be clarified or corrected.

Edit

As noted in my comment, in order to "AJAXify" your page, you don't really want to push everything around in your Model. Instead, it sounds like you want something like this:

Controller action:

public JsonResult GetPagedData(int page, int itemsPerPage, string[] filters)
{
  var results = dataRepository.GetPagedItems(pageId, itemsPerPage, filters);

  return new JsonResult()
  {
    Data = results.ToArray();
  };
}

JS changes:

var retrieveData = function(path, pageNumber, pageSize, filters, fnHandleCallback) {
  // Use the getJSON method to call our JsonResult action
  $.getJSON(path, { page: pageNumber, itemsPerPage: pageSize, filters: filters }, function(data) {
    fnHandleCallback(data);
  });
};

// The path parameter is our JSON controller action
function updateList() {
  retrieveData("/Controller/GetPagedData", $("#pageNumber").val(), $("#dropDownId").val(), null, handleResponse);
}

I've intentionally ignored figuring out both the page number and the filters - they would follow essentially the same principles.

Finally, when you're rendering the data you'll put it into your product grid rather than another drop-down.

GalacticCowboy
Thanks for the detailed example. Unfortunately, my ViewModel for this page is more complex than your example. ^_^I have:ProductCatalogBrowserModel which contains 5 datasets within it (ProductMenu, ProductMenuByProductTypeView, ProductDetail, ColorFilterList, LifestyleFilterList). With that in mind, how do I pass back the whole thing - which is my Model object in the page?
Keith Barrows
So your Model contains all of the data for your page? One of the things AJAX/JSON will really help with is to lower the amount of data you're pushing around all the time. For example, only send enough initially to show the page, and then use AJAX/JSON to retrieve the rest of the page data "on-demand", such as when a drop-down selection changes.
GalacticCowboy
Keith Barrows
<div class="Columns"> <ul> <% foreach(RoomsAlive.Models.ProductDetail myRecord in Model.ProductDetail) { %> <li> <a href="<%= Url.Action("Types", "Catalog", new { controller = "Catalog", action = "Types", group = myRecord.ProductGroupName, type = myRecord.ProductTypeName }) %> "> <img width="190" height="190" src="http://staging1.roomsalive.com/textures/<%= myRecord.URL_Thumbnail %>" alt="<%= myRecord.ProductTypeName %>" /> <br /> <span class="visible">
Keith Barrows
<%= myRecord.ManufacturerCompanyName %><br /> <%= myRecord.ProductSeriesName %> - <%= myRecord.ProductName %><br /> MSRP: $<%= myRecord.SKU_BasePrice %><br /> [Label] in <%= myRecord.ProductTypeName %><br /> </span> <span class="floater"> Product Description: <%= myRecord.ProductDescription %> <hr /> Product Series Description: <%= myRecord.ProductSeriesDescription %> </span>
Keith Barrows
</a> </li> <% } %> </ul></div>
Keith Barrows
(Man, that looks ugly in the comments!)Basically, when originally rendering the page it creates X amount of <DIV> sections - 1 for each product. If, through AJAX, I increase the number of products per page I don't have the extra <DIV> elements to populate.It almost feels like the correct way to do this is to force a post back each time the user changes something.
Keith Barrows
The beauty of AJAX is that you're writing directly to the DOM, so you create your own DIV tags when you need them - they don't have to already exist on the page.
GalacticCowboy
Thanks. This has me started in the right direction! A lot of work yet to do and I will be posting more questions. :)
Keith Barrows
See "http://stackoverflow.com/questions/830520/-ajax-not-returning-data" to help me finish this off. The (data) piece is popping an error of "data is not defined"...
Keith Barrows