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>
rae1
  • 6,066
  • 4
  • 27
  • 48
Jatin
  • 4,023
  • 10
  • 60
  • 107
  • What does the javascript look like? – gislikonrad Sep 06 '11 at 11:44
  • can you explicitly define what exactly doesn't work? what part of javascript doesn't work after the renderpartial ? – Rafay Sep 06 '11 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. – Jatin Sep 06 '11 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. – Tom Styles Sep 06 '11 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? – Jatin Sep 06 '11 at 13:14
  • Nirvan, when you say "doesn't appear in the page" what do you mean? Have you checked the code that is returned when your partial loads, using something like Firebug or the Chrome equivalent. Yes please post the javascript it will help to see what the issue might be. – Tom Styles Sep 06 '11 at 13:28
  • Tom, if I pack up the javascript code in a .js file and provide a link to that .js file in my PartialView, then the it works properly. If the javascript is embedded in my Partial View inline, then somehow it doesn't appear in my final View. So I am confused now as to why the inline javascript doesn't get into my PartialView when rendered. I am editing my question to include part of my embedded javascript code. – Jatin Sep 06 '11 at 14:50
  • Did you try to put residenceStateChanged function before document.ready? – serefbilge Aug 07 '13 at 07:48

4 Answers4

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.

thepirat000
  • 12,362
  • 4
  • 46
  • 72
  • what is the meaning of this line `viewName = this.ControllerContext.RouteData.GetRequiredString("action");` ? what is action variable will hold? – Mou Oct 01 '15 at 12:36
  • 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. – thepirat000 Oct 01 '15 at 14:11
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.

Community
  • 1
  • 1
Garrett Vlieger
  • 9,354
  • 4
  • 32
  • 44
  • 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. – Jatin Sep 06 '11 at 15:44
  • 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. – Garrett Vlieger Sep 06 '11 at 18:34
  • 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. – Jatin Sep 07 '11 at 04:24
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.

Chad Ruppert
  • 3,650
  • 1
  • 19
  • 19
0

Call the javascript function in your ajax success part

learning
  • 11,415
  • 35
  • 87
  • 154
  • 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. – Jatin Sep 06 '11 at 12:49
  • 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. – CrazyCoderz Sep 06 '11 at 15:48