Nieszka
Nieszka

Reputation: 167

MVC3 Nesting Partial Views with a call to Ajax.ActionLink

I am aware of the previous two questions which talk about nesting partial views but the solutions don't work for my design (which might not be the best one but I'm unsure how to adapt it).

Background:

I collect questionnaire responses from users and store them on an sql server as xml files.

I have a partial view which loads a table with all the Responses of a given user, this partialview populates the table with things like Response date, link to xml response document, questionnaire name, link to xml questionnaire document (the questionnaire info is pulled from a different table) and an Ajax ActionLink which redirects to action which parses the two relevant xml documents to print out Question and Answer list (i.e. visualise the response to be human readable) inside the second partial view.

The first partial view contains a div underneath the table which I wish to populate onclick of the Ajax.ActionLink with the second partial view.

Problem:

The answers are rendered correctly however the partial view is loaded into a whole new page, without any styling.

The other solutions to this nesting problem use RenderPartial() however I use return PartialView()

Code:

First Partial View:

       <table>
        <thead>
         <tr><th>headers with other info</th>
             <th>Display(/th>
         <tr>
        </thead>
        <tbody>
         <tr><td>cells with other info</td>
             <td>@Ajax.ActionLink("View", "DisplayResponse","HealthStatus", new { respID = item.UniqueID,qVersion=item.QuestionnaireVersion, qname = item.QuestionnaireName }, new AjaxOptions { UpdateTargetId = "responseDisp" })</td>
        </tbody> 
       </table>
<div id="responseDisp"></div>    <--- **This is the div I wish to populate, does anyone know why it's not working?**

DisplayResponse Action (without the logic for parsing the xml documents)

 public ActionResult DisplayResponse(Guid respID, int qVersion, String qname) {
        var allResponses = ZData.Responses;
        var response = (from r in allResponses
                        where r.UniqueID == respID
                        select r
                            ).First();
        //geting an XML questionnaire document
        var questionnaireDetails = ZodiacData.Questionnaires;
        var questionnaire = (from q in questionnaireDetails
                             where q.Name == qname && q.Version == qVersion
                             select q
                            ).First();
        //creating XMLDocument to read the questionnaire
        XmlDocument xqdoc = new XmlDocument();
        xqdoc.LoadXml(questionnaire.Xml);
        XmlElement qroot = xqdoc.DocumentElement;
        ViewBag.qroot = qroot;
        XmlDocument xrdoc = new XmlDocument();
        xrdoc.LoadXml(response.Raw);
        XmlElement rroot = xrdoc.DocumentElement;
        ViewBag.rroot = rroot;

        return PartialView("_PrintedResponse");
    }

I would be grateful for any help!

Upvotes: 1

Views: 1606

Answers (2)

anAgent
anAgent

Reputation: 2780

First, as mentioned above, you must have a reference to the jquery.unobtrusive-ajax.js file as this will get things "wired" up correctly for you.

This answer is also in response to your comment on your question about how you're passing your models to your views. You are actually making things more complicated for yourself by using the ViewBag for your model.

By using the ViewBag for your models, you will have a harder time finding/fixing/resolving issues in typo's as well as the great features of the Razor helpers. The ViewBag is a dynamic object and there are no compile time type checks. You don't need to cast your objects either (less code).

The preferred (and best practice) is to hook things up like so:

1) Your controller contains ViewModels (Strongly Typed) that are passed to the ViewModels

Controller

    public ActionResult Something() {
        return View();
    }

    public ActionResult UserView() {
        UserViewModel mdoel = new UserViewModel {
            Email = "[email protected]",
            FirstName = "Your",
            SStatuses = new List<SStatus>{
                new SStatus {
                    ID = 0
                }
            }
        };
        return PartialView("_SomethingPartial", mdoel);
    }

Index ("Something" view)

@{
    ViewBag.Title = "Something";
}

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<h2>Something</h2>
@Ajax.ActionLink("Ajax Click", "UserView", new AjaxOptions { UpdateTargetId = "MyDivContainer", InsertionMode = InsertionMode.Replace })
<div id="MyDivContainer">
<!-- my content should be here -->
</div>

Partial View

@model StackModels.UserViewModel
<div class="par">
    @Html.LabelFor(m => m.FirstName)
    <div class="field">
        @Html.TextBoxFor(m => m.FirstName)
        @Html.ValidationMessageFor(m => m.FirstName)
    </div>
</div>

Upvotes: 1

nemesv
nemesv

Reputation: 139758

In MVC3 the @AJax. helpers are rendering regular form and a tags with some extra data- attributes. To make the magic work some Javascript is needed which will use this generated data- attributes to make the necessary jQuery ajax calls.

These js functions are living in the jquery.unobtrusive-ajax.js so add this line to your layout or view and it should work:

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" 
        type="text/javascript"></script>

Upvotes: 2

Related Questions