开发者

How to load a partial view containing JavaScript?

开发者 https://www.devze.com 2023-04-03 12:12 出处:网络
In one of my View pages I have a asp.net mvc PartialView. The PartialView contains some javascript (and jquery). In my asp.net main View I load the PartialView using ajax, within a div tag, in way giv

In one of my View pages I have a asp.net mvc PartialView. The PartialView contains some javascript (and jquery). In my asp.net main View I load the PartialView using ajax, within a div tag, in way given below. That is, from controller I return PartialView("_DonorEdit") and in my main page I use javascript to replace the content of the div tag with the PartialView response.

<div class="content" id="content">
    @{Html.RenderPartial("_DonorEdit");}   
</div>

Everything works fine except the javascript contained in the partialView (_DonorEdit). Thus the question boils down to - How do I have javascript embedded in an div tag and still get it working correctly.

This problem occurs only when the partial view is returned from the ajax call. In the above code, if I directly include the PartialView (on non-ajax request), then the javascript works properly. But if I later replace the content of div using ajax request, the javascript included in PartialView does not work. The embedded javascript simply does not appear along with the Partial View. So there seems to be some other reason, why the javascript embedded in Partial View does not get passed to browser after the ajax request success开发者_开发技巧.

The part of my javascript code

<script type=...>
//Date Picker. This works. I get Calendar popup as expected

$(document).ready(function () {
    $("#Donor_BirthDate").datepicker({
        dateFormat: "dd-mm-yy",
        changeMonth: true,
        changeYear: true,
        yearRange: "-75:+0"
    });

    $("#Donor_DateLastDonated").datepicker({
        dateFormat: "dd-mm-yy",
        changeMonth: true,
        changeYear: true,
        yearRange: "-20:+1"
    });
});


//Dropdown handler. Does not make it in my final View.

function residenceStateChanged(e) {
    var url = '@Url.Action("_GetCities", "DropDown")';
    var cmbResidenceCityId = $('#ResidenceCityId').data('tDropDownList');
    cmbResidenceCityId.loader.showBusy();

    $.ajax({
        type: 'GET',
        url: url,
        data: { StateId: e.value, AddSelectOption: true, SelectOption: 'Select' },
        traditional: true,
        success: function (resp, textStatus, jqXHR) {
            cmbResidenceCityId.dataBind(resp);
            cmbResidenceCityId.select(0);
            cmbResidenceCityId.trigger.change();
        },
        error: function (jqXHR, textStatus, errorThrown) {
            alert(jqXHR.responseText);
        },
        complete: function () {
            cmbResidenceCityId.loader.hideBusy();
        }
    });
}

....//Some other code omitted. Does not make it in final view.
</script>


I believe your problem is related to this one:

Calling a jQuery function inside html return from an AJAX call

Take a look and see if it helps.


Another way to solve the problem, is to render the partial view in the controller, an return back the html in a json object, as the ajax call result.

In the Controller, you can have a generic method to render a partial view:

private string RenderPartialView(string viewName, object model)
{
    if (string.IsNullOrEmpty(viewName))
    {
        viewName = this.ControllerContext.RouteData.GetRequiredString("action");
    }
    this.ViewData.Model = model;
    using (var sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(this.ControllerContext, viewName);
        var viewContext = new ViewContext(this.ControllerContext, viewResult.View, this.ViewData, this.TempData, sw);
        viewResult.View.Render(viewContext, sw);
        viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
        return sw.GetStringBuilder().ToString();
    }
}

Then, you will have to add a new action method to your controller that returns the rendered view, i.e.:

public JsonResult GetDonorEdit()
{
    return Json(new 
    { 
        DonorEditContent = RenderPartialView("_DonorEdit", null) 
    });
}

In client side, the ajax call can be changed to something like this:

$.ajax({
    type: "POST",
    url: "GetDonorEdit",  // get the correct url of GetDonorEdit action
    cache: false
})
.success(function (result) {
    $("#content").html(result.DonorEditContent); 
})
.error(function (xhr, errStatus, errThrown) {
    //...
});

I use this technique, because usually have to return more than one partial view in the same ajax call, and also because it properly execute the javascript code inside the partial views.

Hope it helps.


Call the javascript function in your ajax success part


If you are using this function in multiple pages, why not include it in a script file (maybe named _DonorEdit.js) and including for those pages that use the partial?

You could use something like require.js to make management of this easier. Alternatively to require.js you can use asset bundling like Cassette.net to manage the dependencies for the pages and any partials you load via ajax.

Then, like in your binding/trigger calls inside of your ajax success handler, you can register whatever events/handlers you need to for the partial.

In the long term something you might want to look at is knockout.js: creating a viewmodel in that _DonorEdit.js file that binds against a template returned in your partial can be extremely powerful and maintainable. If you prefer to still render all the data for the partial serverside, you can still take advantage of knockout's event binding to some degree.

0

精彩评论

暂无评论...
验证码 换一张
取 消