Hamid Reza Hamid Reza - 3 months ago 17
Ajax Question

How to set a title for a label with jQuery AJAX?

I want to see a title for the label on mouse enter and I want to get the title text with ajax method.
My HTML code is like the following:

<div id="class">
<label id="cost">@Html.DisplayFor(modelItem => item.PriceId)</label>
</div>


And this is my jquery code:

$("#cost").live("mouseenter", function () {
$.getJSON('/Price/AjaxGetByPriceId', { id: $(this).val() }, function (data) {
for (i = 0; i <= data.length; i++) {
$(this).attr("title", data[i].Url);
}
});
});


And this is my code in my Price controller:

[HttpGet]
public ActionResult AjaxGetByPriceId(int id)
{
var price = priceApp.GetByPriceId(id);

return Json(price, JsonRequestBehavior.AllowGet);
}


But the request is not sent after entering the mouse. What is wrong?

Answer

Html.DisplayFor() generates text, not an input field. So you should not use the $(this).val() method but $(this).html() instead. Also since your controller expects an integer parameter make absolutely sure that this text actually represents an integer, otherwise your controller action will not be hit and you will get an error message saying that the value cannot be parsed to a number. Also inside your AJAX success callback this no longer refers to the element that was used in the mouseenter callback. You should capture it in a closure if you want to use it back:

$("#cost").live("mouseenter", function () {
    var $label = $(this);
    var id = $label.html();
    alert(id); // this should be a number

    $.getJSON('/Price/AjaxGetByPriceId', { id: id }, function (data) {
        for (i = 0; i <= data.length; i++) {
            $lavel.attr("title", data[i].Url);
        }
    });
});

I would also recommend you replacing the .live function (which is completely deprecated and even removed in jQuery 1.9) with the .on() function. And in addition to that I would recommend you using url helpers to generate the url to your controller action instead of hardcoding it as you did.

And yet another remark: it looks like div you have shown is in a foreach loop (I can tell that by the modelItem => item.PriceId lambda you have used where I assume item is your current item of the loop). But the problem here is that you cannot have multiple elements in your DOM with the same id. So what you have shown is invalid markup. You could use a class selector instead:

<div>
     <label class="cost" data-url="@Url.Action("AjaxGetByPriceId, Price")">
         @Html.DisplayFor(modelItem => item.PriceId)
     </label>
</div>

and then:

$(document).on('mouseenter', '.cost', function () {
    var $label = $(this);
    var id = $label.html();
    var url = $label.data('url');
    $.getJSON(url, { id: id }, function (data) {
        for (i = 0; i <= data.length; i++) {
            $label.attr('title', data[i].Url);
        }
    });
});

Also I am not quite sure why are you looping in your AJAX callback:

for (i = 0; i <= data.length; i++) {
    $label.attr('title', data[i].Url);
}

Isn't your controller action supposed to return the title of the corresponding label with the specified id? That would be more correct.

Comments