14

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>
8
  • What does the javascript look like? Commented Sep 6, 2011 at 11:44
  • can you explicitly define what exactly doesn't work? what part of javascript doesn't work after the renderpartial ? Commented Sep 6, 2011 at 11:46
  • @Gisli, There are some dropdown menus in my Partial View. To handle for events like onchange for these dropdowns, I have some javascript code which is the code in question (ie not working because it gets included in div tag). Since, the Partial View gets included in a number of Main Pages, I have this javascript code embedded in the included file (Partial View), instead of replicating it in all my Main Views. Commented Sep 6, 2011 at 12:46
  • Are the javascript functions wrapped in a jQuery document.ready() function or something similar, because document.ready() will have fired long before you load your partial. Commented Sep 6, 2011 at 13:07
  • @Tom, Infact it is the other way. The JQuery code included in the document.ready() works properly. But the other functions defined outside of jquery document.ready() simply doesn't appear in the Page. This is where I get reference error ("function xxx is not defined"). Shall I paste my javascript code here in my question? Commented Sep 6, 2011 at 13:14

4 Answers 4

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

At first I thought this would solve the problem, so I tried setting datatype to "html". But I still get MissingReference (in chrome), stating that the the javascript function is not available.
Can you see the JavaScript function in the code using Firebug? Can you inspect the HTML that's returned from the AJAX call (again, using Firebug and the Net tab)? If the function isn't actually being returned from your AJAX call, something is wrong with the partial View.
I used fiddler to check what response comes from the server. The javascript functions defined in PartialView come as a part of response from the server. So the server code is fine and it returns correct response. The problem is that when I Inspect the html in the rendered View, I don't see these functions. The partial view is part of a Telerik Modal Window. I hope it is not because of telerik window that this problem appears (ideally it shouldn't be). So in short, response contains the embedded javascript, but the rendered html does not have it.
1

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.

2 Comments

what is the meaning of this line viewName = this.ControllerContext.RouteData.GetRequiredString("action"); ? what is action variable will hold?
That's to get the current action name, in case the viewName is not specified it will assume a view with the same name as the action.
0

Call the javascript function in your ajax success part

2 Comments

There are some functions which are event based. I cannot simply call the javascript function. These functions get executed whenever some event like onchange occurs in one of my dropdowns.
Depending on what your javascript is looking for the OnSuccess usually works. You can also try including the script in $(document).ready of you partial.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.