Sunday, April 17, 2011

ASP.NET MVC View and jQuery.data()

Scenario:

I have a partial view that is used in several places across my ASP.NET MVC application. The partial view contains a list of "objects" to select, i.e. something similar to:

<ul>
    <%
        foreach (var person in Model.Persons)
        {
    %>
    <li><a href="#" class="person">
        <%= person.Name %></a></li>
    <%
        }        
    %>
</ul>

Each person has a unique id.

I use jQuery for my AJAXy stuff, and up until now I have added click functionality to the links in the following way (although it has a very non-jQuery-like smell)

<a href="#" class="person" onclick="return selectPerson('<%= person.Id %>');">
            <%= person.Name %></a>

It works and all, however it also requires me to have a selectPerson() javascript function on each page using this partial view (since what happens in the select is "special" for each view).

I just stumbled upon the jQuery Data() method and it seems to be able to support my needs, i.e. in the views using my partial person list view I could do something like:

$("a.person").click(function() { alert($(this).data("personId")); return false; });

If I have the Id's attached to the "personId" data property on the DOM elements.

Now the problem I have is that I do the HTML rendering server side, but the attaching of the "personId" data property to the DOM elements must be done client side. I.e. either during the foreach loop or in a separate JS loop but I would prefer to avoid that.

Maybe I'm going down the wrong path, I dunno, but maybe somebody has a solution for this or maybe a better approach?

Edit (updated for clarity):

Somehow execute

$(select the "current" anchor).data("personId", set to value of person.Id);

From stackoverflow
  • A better approach would be to use unobtrusive javascript. You generate your link as normal:

    <a class="person" href="http://example.com/persons/select?id=<%= person.Id %>"><%= person.Name %></a>
    <!-- or use helpers to generate the link -->
    <%= Html.RouteLink(person.Name, "Default", new RouteValueDictionary(new { controller = "Persons", action = "Select", id = person.Id })) %>
    

    and then ajaxify it:

    jQuery(function() {
        jQuery('a.person').click(function(evt) {
            jQuery.ajax({
                url: this.href,
                success: function(data) {
                    // Do something with the returned content
                }
            });
        });
    });
    

    I didn't quite understand why would you want to use JQuery.data()

    veggerby : I haven't really thought of something like this, however I can't use a link/url. This could equally well be used in a Drag-n-Drop situation, where I then async. add a person to say a group (which could be created like you suggest). I need to know "which person" or an alt. approach.
  • Why don't you "dump" your person id into the ID field of the link.

    <a href="#" class="person" id="person_<%= person.Id %>"><%= person.Name %></a>
    

    Now that you have the id, you can use you jQuery to attach the click event to each link with the person class, like darin showed:

    jQuery(function() {
        jQuery('a.person').click(function(evt) {
            return selectPerson(this);
        });
    });
    

    Now in the selectPerson function, or in the above stated function you have to get the id of the element (which will be like person_234) and take off the person_ part and you're done.

    veggerby : Of course that could work and I have thought of that, but IMHO - and you can call me idealistic :) - but there has got to be a better/cleaner way of doing this i.e. keep my data "structured". Also with jQuery.data() I could potentially attach an entire object not just "the key".
    veggerby : Albeit not the best solution, this was the path I chose, due to "lack" of a better way :( / :)
  • You can use the jQuery Metadata plugin.. basically it's using json data in the class property, which is automatically serialized when accessed..

    But it adds a lot of markup though..

    see http://plugins.jquery.com/project/metadata for reference.

    Cheers,

    Erik

0 comments:

Post a Comment