Post selected item using jQuery selectable plugin with ASP.NET MVC 2
I have an application under development using ASP.NET MVC 2 with jQuery. I have a list of items displayed in my page and a set of actions that can be performed on each item. Rather than repeat the links or icons for each list item, we are displaying them in a pseudo-toolbar at the top of the list.
I am using the jQuery UI Selectable plug-in to manage selecting the list items. Now I need to accomplish two things:
When I click one of the buttons, I need to submit the id of the selected list item as an argument to the request. For example, if I click the "Edit" button, it should correspond to the action method Edit(int id) with 'id' being pulled from the selected item in the list. (Btw, 'id' is not the element id开发者_Go百科 but the identifier from the server that I need to embed in the response so I can use it to identify the item back on the server.)
I want to be able to enable/disable buttons based on other factors. For example, perhaps one list item can't be edited because it is 'closed.' Once I am able to determine which item is selected (using $(".ui-selected") I presume), what is the best way for me to communicate the other attributes I need to determine which buttons are enabled or disabled? Are hidden fields my only (best) option to pass such info to the client-side script?
UPDATE
After reading more I feel I should clarify that I do NOT want to perform the action asynchronously - so no AJAX. I am looking at using the normal action-link type behavior for the buttons.
I haven't used the jQuery UI Selectable plugin specifically, but I did just finish developing something very similar to what you are describing, so I'll offer my 2 cents on it. If there are a lot of properties that determine the actions available to take against a given object, I would recommend putting a form in each row (or div, or however you are laying these out) that provides all the properties you need to determine which actions can be taken. This will allow you to take advantage of jQuery's .serializeArray() method which is pretty useful. So if you have a table row for each object, it may look something like this:
<table>
<tr>
<td>
<form>
<input type="checkbox" name="id" value="1" />
<input type="hidden" name="color" value="red" />
<input type="hidden" name="size" value="large" />
</form>
</td>
</tr><tr>
<td>
<form>
<input type="checkbox" name="id" value="2" />
<input type="hidden" name="color" value="orange" />
<input type="hidden" name="size" value="small" />
</form>
</td>
</tr>
</table>
Depending on when you wish to run your logic which determines which actions can be taken (for example, after each time a checkbox is checked) your javascript may look something like this:
$(function(){
$('[name="id"]').bind('click', function(){
var actionableObjects = [];
$.each( $('[name="id"]'), function(){
if($(this).is(':checked')){
var obj = {},
arr = $(this).parents('form:first').serializeArray();
$.each(arr, function(index, p){ obj[p.name] = p.value; })
actionableObjects.push( obj );
}
})
updateActionIcons( actionableObjects );
})
})
This should give you a nice clean array of JSON objects to work with.
I'm not sure if this is the best way to go about this, but it worked for me.
As far as submitting the data in the end, I would just create a new form with jQuery once the action button is clicked and do a .trigger('submit') on it if you don't wish to use AJAX.
This is also my first time submitting an answer, so I hope it came through formatted well enough to make sense of.
For the sake of closure, here's what I ended up with (please comment if you have a better solution!):
In my View, I have implemented a "stub" form like this:
<% using (Html.BeginForm("Command", "MyController"))
{ %>
<%= Html.Hidden("CommandName") %>
<%= Html.Hidden("CommandArgument") %>
<% } %>
As mentioned above, I am using the jQuery Selectable plug-in to manage the list of items and their selection. Each item contains hidden fields for any data-points I need to use to determine which of the buttons are enabled or disabled. Here is how I have implemented the Selectable plug-in:
var selectedValue = null;
var selectedItemHasChildren = false;
$(function () {
$(".my_list").selectable({
filter: "tr",
selected: function (e, ui) {
var item = $(ui.selected).children("td");
selectedValue = item.children("input[name=ItemID]").first().val();
selectedItemHasChildren = (item.children("input[name=HasChildren]")
.first()
.val() == 1);
UpdateButtonStates();
}
});
});
The UpdateButtonStates method uses the two variables to determine which buttons should be visible and/or enabled.
Each button, in my case, is actually implemented as an image button - so a span with an <a> wrapper. The href property is directed towards the following method:
function Button_Click(action) {
$("#CommandName").val(action);
$("#CommandArgument").val(selectedValue);
$("form").submit();
}
As you can see, I'm using the form defined above to pass the desired action and the supporting argument back to my controller. I could have, of course, eliminated the CommandName form field and redirected the form itself to the desired action using something like $("form").attr("action", action). I chose to go this route because I didn't want the individual actions exposed by my API. Plus I thought this was convenitently similar to the Command event exposed by traditional ASP.NET Button server controls so the learning curve for other developers would be minimized.
精彩评论