I'm creating an application in Asp.NET MVC. The main page will consist of a couple of tabs, for example, Students & Courses.
There will be a Student model and Course model. I'd like to have a Controller for each that would contain New, Edit, Delete Actions. The front end will look similar to this..
I'd like to use partial views within the body of each tab. Taking the first tab as an example, when the page loads it will display a list of Students in the tab body as a partial view. On clicking 'Add Student' within this partial view it will call an Action in the Student Controller and then return and display a partial view in the tab body with a form to create a new Student. On posting this form it will then again show the Student list partial view in the tab body.
Could anyone point me in the right direction or suggest a clean approach to achieve this?
A thought I had would be to have a partial view for each Action, for example:
<div class="tab-content" style="margin-top:20px;margin-left:10px;">
<div class="tab-pane fade active in" id="page-config-tab">
#Html.Partial("~/Views/Student/_List.cshtml")
#Html.Partial("~/Views/Student/_Add.cshtml")
#Html.Partial("~/Views/Student/_Edit.cshtml")
</div>
<div class="tab-pane fade" id="candidates-tab">
#Html.Partial("~/Views/Course/_List.cshtml")
#Html.Partial("~/Views/Course/_Add.cshtml")
#Html.Partial("~/Views/Course/_Edit.cshtml")
</div>
</div>
And when a button is clicked, I will use Jquery to Hide/Show the relevant partial view in a div before calling the Action in the Controller?
Thanks
You can use AJAX to call the necessary action which returns the correct partial view. Rendering them all on page load is wasteful since only 1 partial view will be displayed at a time.
Your initial HTML should looks like the following, only rendering the view you need:
<div class="tab-content" style="margin-top:20px;margin-left:10px;">
<div class="tab-pane fade active in" id="page-config-tab">
#Html.Partial("~/Views/Student/_List.cshtml")
</div>
<div class="tab-pane fade" id="candidates-tab"></div>
Then, add a script block:
<script>
$(function() {
$('#addStudentBtn').click(function() {
$.ajax({
method: 'GET',
url: '#Url.Action("Add", "Student")',
success: function(data) {
$('#page-config-tab').html(data); // 'data' will be your partial view
}
});
});
});
</script>
I've shown you a bare-minimum example for adding a student, you can use this general approach for each action.
P.S. looks like you're using bootstrap - they have event handlers you can use when changing tabs: https://getbootstrap.com/docs/3.3/javascript/#tabs-events
Related
For example i have an Edit Order View and want to add articles or change the customer using a Modal.
At the moment i render the lists using a ViewComponent whÃch get the full list of all customers and articles inside the Modal (works fine). But now i realized that when i have hundreds of customers and articles i will always load everything inside the Edit Order View.
I there a way to load and unload the content only when i open the modal (preferably using C#)? Or is it no problem to fill the View with all this data?
Ok got it run like this with a new frustating problem
First my Solution:
EditView (Where Modal has to PopUp)
The MenuButton
Customer
At the End, the Modal:
<div class="modal show" id="signup" tabindex="-1" role="dialog" backdrop="true" aria-labelledby="CustomerListModal"></div>
The CustomerController
public ActionResult _CustomerListPartial(string id)
{
ViewBag.id = id;
return PartialView(customRep.ReadCustomerList());
}
The JavaScript loads the Partial
$(function () {
$('body').on('click', '.modal-link', function (e) {
e.preventDefault();
$.get($(this).data("targeturl"), function (data) {
$(
'<div id="modal-container" class="modal fade"> <div class="modal-dialog modal-lg" style="width:80%">' +
'<div class="modal-content" >' +
data +
'</div></div></div>').modal();
});
});
});
The Table (Inside the PartialView) works fine.
My last Problem (and i tried absolute everything) is that i cant use BootstrapTable.
I already tried several positions where i included the JavaScripts.
And i tried to use this:
<script type="text/javascript">
$('#table').bootstrapTable();
</script>
I tried it in seperate PartialViews, _Layout, EditView.... everywhere
BoostrapTable works fine in "normal" Views or ViewComponents but not in this Partial!
Maybe someone has an idea...thanks in advance
I've written a system using ASP.NET MVC that generates various financial reports. Each report is in it's own controller, each controller has its own "Report" Action. The Action Renders a partial view with the report in the ViewBag which it passes to javascript on the front end and puts the rendered element in a JQueryUI dialog.
A user may run a Balance Sheet report then another user may run an Income Statement report, after the first user runs the Balance Sheet Report and instead of seeing the Income Statement, the second user sees the Balance Sheet.
This is the code that returns the report as a JSON object
//Initialize report and add datasources etc.
reportViewer.LocalReport.Refresh();
ViewBag.ReportViewer = reportViewer;
return Json(JsonResponse.Success(RenderRazorViewToString("PrintVoucher", null)));
Here is the Partial View
#using ReportViewerForMvc;
<div class="col-md-12 col-lg-12 col-sm-12 col-xs-12">
#Html.ReportViewer(ViewBag.ReportViewer as Microsoft.Reporting.WebForms.ReportViewer)
</div>
Any advice or guidance would be greatly appreciated!
We ran into the same issue and it seems to be related to a concurrency bug in the ReportViewerForMvc. Stumbled on this old github link which had the information and proposed fix. Hope this helps.
https://github.com/nrifath2009/ReportViewerForMvc/pull/1
Try making your partial view a strongly typed view for "reportViewer" using it in the #Html.ReportViewer() and not the view bag.
After that go to the code that returns that partial view and on return set that as
return Json(JsonResponse.Success(RenderRazorViewToString("PrintVoucher", reportViewer)));
Make sure that your Action have no OutputCache attribute to make
sure the server always calculate new report for each request or Set
VaryByParam on attribute constructor
Use strongly type model instead of ViewBag
Initialize new object of the ReportViewer on each call instead of using a single static object.
Use PartialView on Controller action and pass the report object to the PartialView, Razor engine will process the Partial View with the model and generate an HTML markup as a return for the json call.
Here a working Sample of the controller and the View (I've used Bootbox instead of JqueryUI)
Controller :
[HttpPost, ValidateAntiForgeryToken]
public PartialViewResult Report(/*Pass Optional Parameters If Required*/)
{
var reportViewer = new ReportViewer();
//reportViewerInitialization
return PartialView("PrintVoucher", reportViewer);
}
JavaScript Method for loading Report View
function showReport(reportControllerName)
{
var dialog = bootbox.dialog({
message: '<p><i class="fa fa-spin fa-spinner"></i> Loading...</p>'
});
$.ajax({
type: "POST",
url: '/'+ reportControllerName +'/Report/',
data: {/*DataPassed To The Report Action*/},
success: function (data) {
//data Field will contain an Html markup resulted from razor engine process for PrintVoucher PartialView
dialog.find('.bootbox-body').html(data);
}
});
}
PrintVoucher.cshtml
#using ReportViewerForMvc;
<div class="container">
<div class="row">
<div class="col-md-12 col-lg-12 col-sm-12 col-xs-12">
#Html.ReportViewer(Model as Microsoft.Reporting.WebForms.ReportViewer)
</div>
</div>
</div>
in my MVC action I have
return PartialView("partialView", model);
I have this in the parent View:
<div id="myModal" class="modal fade in">
<div id="modalContainer">
</div>
</div>
And the body of the modal in the partial View.
I used this as a template: Using Bootstrap Modal window as PartialView
The modal loads fine with the right data on submit of the page. The problem is that the partial view with the modal covers the entire parent view instead of just showing the modal.
There's essentially the modal with a blank white screen.
My question is how would I only show the modal with data, and prevent the partial view from covering the whole page?
Thanks a million!
My question is how would I only show the modal with data, and prevent
the partial view from covering the whole page?
I would try rendering the modal without data to start. First and foremost make sure your modal appears and has some content in to start. Something simple like 'loading data...' or anything in your starting Modal Html will assist in rendering data. Once you connect to your Controller code you will be able to walk the code after "return partial view" and you should NOT step into your _Layout code.
Once you add your partial view, do yourself a favor and wrap it with a cascading style sheet (CSS) class that makes it very obvious that the style is working. Something as simple this should help.
<style type='text/css'>
.wrapper{
border:solid 1px red;
}
</style>
<div id="myModal" class="modal fade in">
<div id="modalContainer" class='wrapper">
</div>
</div>
What is the best method to render some navigation hyperlinks depending on which page the user is on (I am using C# MVC 4).
I have a _layout.cshtml which looks like the following (shortened down for display purpose).
<body>
#{Html.RenderAction("MainNav", "Navigation");}
<div id="container">
#RenderBody();
</div>
</body>
If a user navigates to /Home/Index then I would want the MainNav to render hyperlinks of Home | Management
Then if a user clicks Management that will change to Home | Company | Teams | Roles and will change again if they click one of these links.
Using Html.RenderAction() or Html.Action() would involve passing a parameter identifying your current view and using multiple if/else blocks to define what the partial should render. Instead you can use Razor sections to act as placeholders for specific content that can be placed anywhere in the layout.
In the layout, add #RenderSection(), in this case named "menu" to act as a placeholder for your menu links
<div id="sidebar">
#RenderSection("menu", required: false)
</div>
<div id="container">
#RenderBody();
</div>
Then in each view, add #section menu { ... } containing the links to display
Index.cshtml
// content to be displayed
#section menu {
#Html.ActionLink("Home", .....)
#Html.ActionLink("Management", .....)
}
Management.cshtml
// content to be displayed
#section menu {
#Html.ActionLink("Home", .....)
#Html.ActionLink("Company", .....)
#Html.ActionLink("Teams", .....)
#Html.ActionLink("Roles", .....)
}
The more you think about it, the more complex the problem you're describing becomes. So I tend to use a library. Even though it might seem overkill at this point, but in my experience it pays off later:
<body>
#Html.MvcSiteMap().Menu()
<div id="container">
#RenderBody();
</div>
</body>
This is all you need to do when using https://github.com/maartenba/MvcSiteMapProvider
Install-Package MvcSiteMapProvider
Just annotate your actions like this:
[MvcSiteMapNode(Title = "Menu Title")]
I am using MVC4, C# and visual studio ultimate 2013 in a project.
I am redirecting a user to an index page after submiting a form. However, this webpage has 2 tabs, and I want to redirect the user to the second tab, instead of the first one.
I have a Controller called Material, with an Index action, which sends the user to the Index View.
public ActionResult Index()
{
return View();
}
This View is made of two partial Views, _Materials and _Packages.
#{
ViewBag.Title = "Index";
}
<div class="tabbable">
<ul class="nav nav-tabs">
<li class="active">Materials</li>
<li>Packages</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="Materials">
#Html.Action("Materials", "Material")
</div>
<div class="tab-pane" id="Packages">
#Html.Action("Packages", "Package")
</div>
</div>
</div>
After performing a serie of actions in another section of the application, I which to redirect the user to the /Material page, to the second tab, but I have no idea how to do it !
Currently I am using this code, which always redirects to the first tab:
return RedirectToAction("Index", "Material");
How can I fix my problem?
You can't use something like RedirectToAction because it does not have any capability of appending a URL fragment. What you can do is use something like Redirect which just takes a URL string, and then use the URL helper to still dynamically generate the action URL for you:
return Redirect(Url.Action("Index", "Material") + "#Package");
In other words, Url.Action will generate the main URL for you and return it as a string. You can then append the fragment to this string before finally redirecting.
You'll want to use the
Redirect method
Redirect("www.sitename.com/material/index#Package");
or
string fragment = "Package";
Redirect("www.sitename.com/material/index#" + fragment);
The #Package is what is called a Fragment Identifier, that will focus your browser on the part of the page with the id of Package.
You can simply write an Ajax call to pass to the controller and in case of success, append #tab to the url parameter. for example use this: