I have a partial view in my MVC 4 solution that builds a tree view of the servers directory structure. When this partial view is loaded there criteria checkboxes on the the partial view for the user to filter down which drives the domain code will look at.
After which the user presses the Search button and what should happen is the partial view's model is populated and this is sent down to the partial view to rebuild itself.
So I have tried many ways of doing this one of which having an ajax call added to the click event of the Search button:
function BuildExcludedDrives(checkbox) {
var isChecked;
if ($(checkbox).prop('checked')) {
isChecked = 'true';
}
else {
isChecked = 'false';
}
var id = $(checkbox).prop('id');
$.ajax({
url: '@Url.Action("BuildExcludedDrives", "TreeView")',
data: {
isChecked: isChecked,
id: id
},
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function () { }
});
}
This hits the server side code:
public ActionResult RebuildTree()
{
_folderModel.BuildFolderBrowserTree();
return PartialView(_folderModel);
}
But the partial view does not rebuild anything. I know this is down to my lack of knowledge on MVC but I don't understand which returning the updated model has no effect.
I tried making the Action RebuildTree a PartialViewResult, I called it through adding @url.Action("", "") to my button click. The only way it rebuild is if I submit through using @using (Html.BeginForm()) etc. This works in that the data is pushed down
to the partial view but it causes all the page to rebuild to.
If you are returning a PartialView within your Ajax call, you will want to output it into a specific element within your page (like a <div>) in the success function of your AJAX call.
$.ajax({
url: '@Url.Action("BuildExcludedDrives", "TreeView")',
data: {
isChecked: isChecked,
id: id
},
contentType: "application/json; charset=utf-8",
//data will be your return content (the rendered html from your Partial View)
success: function (data) {
//Outputs your data into a specific <div> element (This can be your original TreeView container)
$('#yourOutput').html(data);
}
});
You can see a very basic example of this working below to help explain what is going on :
View
<!-- jQuery Reference -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<!-- Your Script -->
<script type='text/javascript'>
//Your method (dramatically simplified)
function BuildExcludedDrives() {
$.ajax({
url: '@Url.Action("Example", "Default")',
//Passes the content of an input up
data: { id: $('#test').val() },
contentType: "application/json; charset=utf-8",
success: function (data) {
$('#output').html(data);
}
});
}
</script>
<!-- An input that will fire your event -->
<input id='test' onchange='BuildExcludedDrives();' />
<div id='output'>
<!-- Output goes here -->
</div>
Controller
public ActionResult Example(string id)
{
//This will populate the Test Partial View with your value(s)
return PartialView("Test", id);
}
Test Partial View
@model string
<!-- Just for example purposes outputs a button with your value that was passed in -->
<h1>@Model was passed properly!<h1/>
The Ajax postback was one of the ways I was experimenting with but I use a lot of of Razor code to build this partial view so I am really not sure if this would be the best option, that said I am not sure what my options are. Here is the partial view:
@using HomeController.Web.UI.Models
@using System.Collections
@using HomeController.Domain.Configuration.Generic.Entities
@model HomeController.Web.UI.Models.FolderModel
<div id="MediaPlayerAddMediaToLibraryControlPanel" class="fLeft">
<div>
<p>Please use these filters in order to improve performance of the search</p>
</div>
<div id="MediaPlayerAddMediaToLibraryAvailableDrives" class="fLeft">
<p>Select which drives you want the folder browser to look at</p>
@{
foreach (string availableDrive in @Model.AvailableDrives)
{
if (Model.ExcludedDrives.Contains(availableDrive))
{
<input type="checkbox" id="@availableDrive" name="@availableDrive" value="false"/ onclick="BuildExcludedDrives(this)">@availableDrive<br>
}
else
{
<input type="checkbox" id="@availableDrive" name="@availableDrive" value="true" checked="checked" onclick="BuildExcludedDrives(this)"/>@availableDrive<br>
}
}
}
</div>
<div id="MediaPlayerAddMediaToLibraryExcludedPaths" class="fLeft">
<p>Exclude paths you don't want the folder browser to look at</p>
@{
foreach (string excludedPath in @Model.ExcludedPaths)
{
<input type="checkbox" id="@excludedPath" name="@excludedPath" value="false" checked="checked" onclick="BuildExcludedPaths(this)"/>@excludedPath<br>
}
}
</div>
<div id="MediaPlayerAddMediaToLibrarySearchButton" class="fLeft">
<input id="BtnBrowserFolderSearch" type="image" src="~/homecontroller.web.ui/Images/Zoom-01.ico" class="Buttons" onclick="BrowserFolderSearch()" title="Explore the servers directory based on the filters provided"/>
</div>
</div>
<div class="clear2"></div>
<div id="MediaPlayerAddMediaToLibraryTreeView" class="fLeft">
<div id="container"class="demo">
<div id="demo1" class="demo" style="height:800px;">@*TODO*@
<ul>
@TreeView(@Model.FolderCollection)
</ul>
</div>
</div>
@helper TreeView(List<Folder> folders)
{
for (int i = 0; i < folders.Count; i++)
{
<li onclick="FolderClicked(this)" id= "@folders[i].FullPath">
<a href="#"><span>@folders[i].Name</span></a>
<ul>
@TreeView(folders)
</ul>
</li>
}
}
<div>
<script type="text/javascript" class="source below">
function BrowserFolderSearch() {
$.ajax({
type:'GET',
url: '@Url.Action("RebuildTree", "TreeView")',
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (result){
alert('Working');
}
});
}
function BuildExcludedDrives(checkbox) {
var isChecked;
if ($(checkbox).prop('checked')) {
isChecked = 'true';
}
else {
isChecked = 'false';
}
var id = $(checkbox).prop('id');
$.ajax({
url: '@Url.Action("BuildExcludedDrives", "TreeView")',
data: {
isChecked: isChecked,
id: id
},
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function () { }
});
}
function BuildExcludedPaths(checkbox) {
var isChecked;
if ($(checkbox).prop('checked')) {
isChecked = 'true';
}
else {
isChecked = 'false';
}
var id = $(checkbox).prop('id');
$.ajax({
url: '@Url.Action("BuildExcludedPaths", "TreeView")',
data: {
isChecked: isChecked,
id: id
},
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function () { }
});
}
$(function () {
// TO CREATE AN INSTANCE
// select the tree container using jQuery
$("#demo1")
// call `.jstree` with the options object
.jstree({
// the `plugins` array allows you to configure the active plugins on this instance
"plugins": ["themes", "html_data", "ui", "crrm", "hotkeys"],
// each plugin you have included can have its own config object
//"core": { "initially_open": ["phtml_1"] }
// it makes sense to configure a plugin only if overriding the defaults
})
// EVENTS
// each instance triggers its own events - to process those listen on the container
// all events are in the `.jstree` namespace
// so listen for `function_name`.`jstree` - you can function names from the docs
.bind("loaded.jstree", function (event, data) {
// you get two params - event & data - check the core docs for a detailed description
});
});
function FolderClicked(li) {
}
</script>
</div>
</div>
MVC will handle rendering a complex partial view (as your example shows) just as it would one that contained a simple string. You should be fine using AJAX to handle it.
So in the partial view I detailed what should I put in the success part of the AJAX call? Sorry if this is a stupid question but I am really not sure what to do here.
I have noticed when this AJAX call is made I am hitting the Controller's RebuildTree action and the model is returned but in the error part of my AJAX call it is reporting of a 500 internal error exception.
be sure to decorate the type in your ajax tag. specify if it is a post or a get and maybe use fiddler to drill into your ajax error response code, because it is truly difficult to see your ajax response any other way.
i am surprised there is not a built in component that visual studio has made to detect all http requests...
The partial view 'RebuildTree' was not found or no view engine supports the searched locations.
The following locations were searched:
~/Views/TreeView/RebuildTree.aspx
~/Views/TreeView/RebuildTree.ascx
~/Views/Shared/RebuildTree.aspx<
~/Views/Shared/RebuildTree.ascx
~/Views/TreeView/RebuildTree.cshtml
~/Views/TreeView/RebuildTree.vbhtml
~/Views/Shared/RebuildTree.cshtml
~/Views/Shared/RebuildTree.vbhtml
I have set the action RebuildTree of TreeView to be a both ActionResult and
PartialViewResult and get the same error
Here is the AJAX call:
function BrowserFolderSearch() {
$.ajax({
type: 'GET',
url: '@Url.Action("RebuildTree", "TreeView")',
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (result){
$('#demo1').html(data); //This would output your partial view within your demo1 <div>
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.getAllResponseHeaders);
alert(xhr.error);
alert(xhr.status);
alert(thrownError);
}
});
}
yeah your view does not exist. or it is named differently than you first thought. either way the view was not found because your visual studio compiler is wacked and can be fixed by closing and reopening. i have encountered odd errors on windows xp machines
with too much permission settings but in your case you should be good by setting your partial view to do something like Return PartialView("_MyNewUniqueNameRebuildTree")
bigredhf
Member
48 Points
81 Posts
How to update Partial View with doing a submit
Feb 16, 2013 12:22 PM|LINK
Hi,
I have a partial view in my MVC 4 solution that builds a tree view of the servers directory structure. When this partial view is loaded there criteria checkboxes on the the partial view for the user to filter down which drives the domain code will look at. After which the user presses the Search button and what should happen is the partial view's model is populated and this is sent down to the partial view to rebuild itself.
So I have tried many ways of doing this one of which having an ajax call added to the click event of the Search button:
function BuildExcludedDrives(checkbox) { var isChecked; if ($(checkbox).prop('checked')) { isChecked = 'true'; } else { isChecked = 'false'; } var id = $(checkbox).prop('id'); $.ajax({ url: '@Url.Action("BuildExcludedDrives", "TreeView")', data: { isChecked: isChecked, id: id }, dataType: 'json', contentType: "application/json; charset=utf-8", success: function () { } }); }This hits the server side code:
public ActionResult RebuildTree() { _folderModel.BuildFolderBrowserTree(); return PartialView(_folderModel); }But the partial view does not rebuild anything. I know this is down to my lack of knowledge on MVC but I don't understand which returning the updated model has no effect.
I tried making the Action RebuildTree a PartialViewResult, I called it through adding @url.Action("", "") to my button click. The only way it rebuild is if I submit through using @using (Html.BeginForm()) etc. This works in that the data is pushed down to the partial view but it causes all the page to rebuild to.
Thanks Dave.
Rion William...
All-Star
26542 Points
4413 Posts
Re: How to update Partial View with doing a submit
Feb 16, 2013 12:42 PM|LINK
If you are returning a PartialView within your Ajax call, you will want to output it into a specific element within your page (like a <div>) in the success function of your AJAX call.
$.ajax({ url: '@Url.Action("BuildExcludedDrives", "TreeView")', data: { isChecked: isChecked, id: id }, contentType: "application/json; charset=utf-8", //data will be your return content (the rendered html from your Partial View) success: function (data) { //Outputs your data into a specific <div> element (This can be your original TreeView container) $('#yourOutput').html(data); } });You can see a very basic example of this working below to help explain what is going on :
View
<!-- jQuery Reference --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <!-- Your Script --> <script type='text/javascript'> //Your method (dramatically simplified) function BuildExcludedDrives() { $.ajax({ url: '@Url.Action("Example", "Default")', //Passes the content of an input up data: { id: $('#test').val() }, contentType: "application/json; charset=utf-8", success: function (data) { $('#output').html(data); } }); } </script> <!-- An input that will fire your event --> <input id='test' onchange='BuildExcludedDrives();' /> <div id='output'> <!-- Output goes here --> </div>Controller
public ActionResult Example(string id) { //This will populate the Test Partial View with your value(s) return PartialView("Test", id); }Test Partial View
bigredhf
Member
48 Points
81 Posts
Re: How to update Partial View with doing a submit
Feb 16, 2013 02:24 PM|LINK
Hi Rion,
The Ajax postback was one of the ways I was experimenting with but I use a lot of of Razor code to build this partial view so I am really not sure if this would be the best option, that said I am not sure what my options are. Here is the partial view:
@using HomeController.Web.UI.Models @using System.Collections @using HomeController.Domain.Configuration.Generic.Entities @model HomeController.Web.UI.Models.FolderModel <div id="MediaPlayerAddMediaToLibraryControlPanel" class="fLeft"> <div> <p>Please use these filters in order to improve performance of the search</p> </div> <div id="MediaPlayerAddMediaToLibraryAvailableDrives" class="fLeft"> <p>Select which drives you want the folder browser to look at</p> @{ foreach (string availableDrive in @Model.AvailableDrives) { if (Model.ExcludedDrives.Contains(availableDrive)) { <input type="checkbox" id="@availableDrive" name="@availableDrive" value="false"/ onclick="BuildExcludedDrives(this)">@availableDrive<br> } else { <input type="checkbox" id="@availableDrive" name="@availableDrive" value="true" checked="checked" onclick="BuildExcludedDrives(this)"/>@availableDrive<br> } } } </div> <div id="MediaPlayerAddMediaToLibraryExcludedPaths" class="fLeft"> <p>Exclude paths you don't want the folder browser to look at</p> @{ foreach (string excludedPath in @Model.ExcludedPaths) { <input type="checkbox" id="@excludedPath" name="@excludedPath" value="false" checked="checked" onclick="BuildExcludedPaths(this)"/>@excludedPath<br> } } </div> <div id="MediaPlayerAddMediaToLibrarySearchButton" class="fLeft"> <input id="BtnBrowserFolderSearch" type="image" src="~/homecontroller.web.ui/Images/Zoom-01.ico" class="Buttons" onclick="BrowserFolderSearch()" title="Explore the servers directory based on the filters provided"/> </div> </div> <div class="clear2"></div> <div id="MediaPlayerAddMediaToLibraryTreeView" class="fLeft"> <div id="container"class="demo"> <div id="demo1" class="demo" style="height:800px;">@*TODO*@ <ul> @TreeView(@Model.FolderCollection) </ul> </div> </div> @helper TreeView(List<Folder> folders) { for (int i = 0; i < folders.Count; i++) { <li onclick="FolderClicked(this)" id= "@folders[i].FullPath"> <a href="#"><span>@folders[i].Name</span></a> <ul> @TreeView(folders) </ul> </li> } } <div> <script type="text/javascript" class="source below"> function BrowserFolderSearch() { $.ajax({ type:'GET', url: '@Url.Action("RebuildTree", "TreeView")', dataType: 'json', contentType: "application/json; charset=utf-8", success: function (result){ alert('Working'); } }); } function BuildExcludedDrives(checkbox) { var isChecked; if ($(checkbox).prop('checked')) { isChecked = 'true'; } else { isChecked = 'false'; } var id = $(checkbox).prop('id'); $.ajax({ url: '@Url.Action("BuildExcludedDrives", "TreeView")', data: { isChecked: isChecked, id: id }, dataType: 'json', contentType: "application/json; charset=utf-8", success: function () { } }); } function BuildExcludedPaths(checkbox) { var isChecked; if ($(checkbox).prop('checked')) { isChecked = 'true'; } else { isChecked = 'false'; } var id = $(checkbox).prop('id'); $.ajax({ url: '@Url.Action("BuildExcludedPaths", "TreeView")', data: { isChecked: isChecked, id: id }, dataType: 'json', contentType: "application/json; charset=utf-8", success: function () { } }); } $(function () { // TO CREATE AN INSTANCE // select the tree container using jQuery $("#demo1") // call `.jstree` with the options object .jstree({ // the `plugins` array allows you to configure the active plugins on this instance "plugins": ["themes", "html_data", "ui", "crrm", "hotkeys"], // each plugin you have included can have its own config object //"core": { "initially_open": ["phtml_1"] } // it makes sense to configure a plugin only if overriding the defaults }) // EVENTS // each instance triggers its own events - to process those listen on the container // all events are in the `.jstree` namespace // so listen for `function_name`.`jstree` - you can function names from the docs .bind("loaded.jstree", function (event, data) { // you get two params - event & data - check the core docs for a detailed description }); }); function FolderClicked(li) { } </script> </div> </div>Rion William...
All-Star
26542 Points
4413 Posts
Re: How to update Partial View with doing a submit
Feb 16, 2013 02:34 PM|LINK
MVC will handle rendering a complex partial view (as your example shows) just as it would one that contained a simple string. You should be fine using AJAX to handle it.
bigredhf
Member
48 Points
81 Posts
Re: How to update Partial View with doing a submit
Feb 16, 2013 03:19 PM|LINK
So in the partial view I detailed what should I put in the success part of the AJAX call? Sorry if this is a stupid question but I am really not sure what to do here.
I have noticed when this AJAX call is made I am hitting the Controller's RebuildTree action and the model is returned but in the error part of my AJAX call it is reporting of a 500 internal error exception.
Rion William...
All-Star
26542 Points
4413 Posts
Re: How to update Partial View with doing a submit
Feb 16, 2013 03:54 PM|LINK
You would want to use something like :
$.ajax({ url: '@Url.Action("BuildExcludedPaths", "TreeView")', data: { isChecked: isChecked, id: id }, contentType: "application/json; charset=utf-8", success: function (data) { $('#demo1').html(data); //This would output your partial view within your demo1 <div> } });or depending on where you want to display your partial results, you might use :
$("#MediaPlayerAddMediaToLibraryControlPanel").html(data);bigredhf
Member
48 Points
81 Posts
Re: How to update Partial View with doing a submit
Feb 16, 2013 04:38 PM|LINK
Firstly Rion I must thank you for your help so far, it is really kind of you.
I can;t understand why the AJAX is getting internal server errors when the Controllers method it calls throws no errors at all.
Xequence
Contributor
4303 Points
1528 Posts
Re: How to update Partial View with doing a submit
Feb 16, 2013 04:51 PM|LINK
be sure to decorate the type in your ajax tag. specify if it is a post or a get and maybe use fiddler to drill into your ajax error response code, because it is truly difficult to see your ajax response any other way.
i am surprised there is not a built in component that visual studio has made to detect all http requests...
Credentials
bigredhf
Member
48 Points
81 Posts
Re: How to update Partial View with doing a submit
Feb 16, 2013 05:00 PM|LINK
Sorry I should have thought of using Fiddler:
The partial view 'RebuildTree' was not found or no view engine supports the searched locations.
The following locations were searched:
~/Views/TreeView/RebuildTree.aspx
~/Views/TreeView/RebuildTree.ascx
~/Views/Shared/RebuildTree.aspx<
~/Views/Shared/RebuildTree.ascx
~/Views/TreeView/RebuildTree.cshtml
~/Views/TreeView/RebuildTree.vbhtml
~/Views/Shared/RebuildTree.cshtml
~/Views/Shared/RebuildTree.vbhtml
I have set the action RebuildTree of TreeView to be a both ActionResult and PartialViewResult and get the same error
Here is the AJAX call:
function BrowserFolderSearch() { $.ajax({ type: 'GET', url: '@Url.Action("RebuildTree", "TreeView")', dataType: 'json', contentType: "application/json; charset=utf-8", success: function (result){ $('#demo1').html(data); //This would output your partial view within your demo1 <div> }, error: function (xhr, ajaxOptions, thrownError) { alert(xhr.getAllResponseHeaders); alert(xhr.error); alert(xhr.status); alert(thrownError); } }); }Xequence
Contributor
4303 Points
1528 Posts
Re: How to update Partial View with doing a submit
Feb 16, 2013 05:08 PM|LINK
yeah your view does not exist. or it is named differently than you first thought. either way the view was not found because your visual studio compiler is wacked and can be fixed by closing and reopening. i have encountered odd errors on windows xp machines with too much permission settings but in your case you should be good by setting your partial view to do something like Return PartialView("_MyNewUniqueNameRebuildTree")
Credentials