简体   繁体   中英

How to load a partial view containing JavaScript?

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>

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, ie:

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.

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.

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.

在你的ajax成功部分调用javascript函数

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM