I needed to have a View in my application that has 2 tabs. After struggling, I came up with the following with Bootstap Tabs and Partial Views:
<div id="tabs">
<ul class="nav nav-tabs">
<li class="active">
Optin Status
</li>
<li>
Optin History
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="OptinStatus">
#Html.Partial("_OptinStatus")
</div>
<div class="tab-pane" id="OptiHistory">
#Html.Partial("_OptinHistory")
</div>
</div>
</div>
As long as I do this in my Results action, I can display the two tabs side by side and switch:
public ActionResult Results(OptinStatusViewModel viewModel)
{
// return RedirectToAction("OptInStatus");
return View();
}
The problem is now that I want to do some processing in the controller and display the results in the Partial View. so I switched the above to:
return RedirectToAction("OptInStatus");
That Action Method is supposed to be for the 1st partial view:
public ActionResult OptInStatus(OptinStatusViewModel viewModel)
{
HarmonyOperation harmonyoper = new HarmonyOperation();
ListProfileData res = new ListProfileData();
string listid = "60285206-7c9e-4af3-a0c4-0a69ec8d4bb4"; // Preferences Master List
string email = (string) TempData["User"];
string customerKey = Tools.GetCustomerKeyByEmail(email);
res = harmonyoper.GetProfileFromListByCustomerKey(listid, customerKey);
IDictionary<string, string> profileData = new Dictionary<string, string>();
// Found record in LIST for email
if (res != null)
{
profileData = Tools.ListKeyValueToDictionary(res.attributes);
//Check existence of this email
}
return View("_OptinStatus");
The problem when I do this is I get a new View that displays the "contents" of the Partial View instead of that Partial View in its tab. How can I get data to my partial view?
You're returning a View from your controller, when you should be returning PartialView.
So instead of:
return View("_OptinStatus");
You do:
return PartialView("_OptinStatus", model); //model is not required
And you should get this model in the actual view "_OptinStatus", not in the "main view".
An example of using seperate partial models:
Controllers:
public ActionResult Results()
{
return View();
}
public ActionResult OptInStatus()
{
return PartialView("_OptinStatus");
}
... etc
Results-view:
<div class="tab-content">
<div class="tab-pane active" id="OptinStatus">
#Html.Action("_OptinStatus")
</div>
<div class="tab-pane" id="OptiHistory">
#Html.Action("_OptinHistory")
</div>
</div>
_OptinStatus-partialView:
#model OptinStatusModel
<div>My partial for Status</div>
_OptinHistory-partialView:
#model OptinHistoryModel
<div>My partial for History</div>
The same example using viewModel for both partials:
Controllers:
public ActionResult Results(OptinStatusViewModel viewModel)
{
return View("Results", viewModel);
}
Results-view:
#model OptinStatusViewModel
<div class="tab-content">
<div class="tab-pane active" id="OptinStatus">
#Html.Partial("_OptinStatus", Model.OptionStatusModel)
</div>
<div class="tab-pane" id="OptiHistory">
#Html.Partial("_OptinHistory", Model.OptionHistoryModel)
</div>
</div>
_OptinStatus-partialView:
#model OptinStatusModel
<div>My partial for Status</div>
_OptinHistory-partialView:
#model OptinHistoryModel
<div>My partial for History</div>
My prefered solution:
jQuery, included in _layouts
$(".partialContents").each(function(index, item) {
var url = $(item).data("url");
if (url && url.length > 0) {
$(item).load(url);
}
});
Now, instead of using Razor to render the views, you just use a div (and ajax through the code above):
<div class="partialContents" data-url="/Home/OptInStatus">
HomeController will get hit on action "OptInStatus".
Related
I am using partialviews in each tab. I have 3 tabs.
After I have selected a tab, how to submit a form in a partialview and have it stay on the same tab after posting to controller? I just want to refresh the partialview after saving and hopefully not the whole page.
order controller
public ActionResult order()
{
return View();
}
order.cshtml
<div id="tabs">
<ul class="nav nav-tabs">
<li class="active">General</li>
<li>Item</li>
<li>Total</li>
</ul>
<div id="tabs-1">
#{Html.RenderPartial("_Partial_General_Tab");}
</div>
<div id="tabs-2">
#{Html.RenderPartial("_Partial_Item_Tab");}
</div>
<div id="tabs-3">
Content for Tab 3 goes here.<br />
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$("#tabs").tabs();
});
</script>
_Partial_General_Tab.cshtml
#model Mvc5.Models.ORDERMetadata
#using (Html.BeginForm("Edit", "Order"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
// Set New Order Number
#Html.HiddenFor(model => model.Order_Number, new { #Value = ordernumber })
#Html.TextBoxFor(model => model.Order_Date})
<button id="editorder" type="submit">Save</button>
}
_Partial_Item_Tab.cshtml
#model Mvc5.Models.ORDER_DETAILSMetadata
#using (Html.BeginForm("Item", "Order"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
// Set New Order Number
#Html.HiddenFor(model => model.Order_Number, new { #Value = ordernumber })
#Html.TextBoxFor(model => model.Item})
<button id="edititem" type="submit">Save</button>
}
Edit Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ORDERMetadata model)
{
try
{
// update order
return RedirectToAction("order"); //<----- Is this correct redirecting?????
}
}
Item Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Item(ORDER_DETAILSMetadata model)
{
try
{
// update order
return RedirectToAction("order"); //<----- Is this correct redirecting, do I need to pass what tab it is on?????
}
}
instead of using Html.BeginForm use Html.AjaxForm
My View has list of guests (i got entire list) and on their arrival, I have to mark them as arrived.
I wait for 30 min and submit all details to servers by clicking on submit button.
i will submit, guest ID and arrived status to server
I donot know how to pass last of the active guests from View to server.
My Controller
[HttpPost]
public ActionResult GuestList(GuestListForModel collection)
{
var temp = collection;
return View();
}
MyView
#using (Html.BeginForm("GuestList", "Guest"))
{
#foreach (var saiList in Model.GuestArrivalInfoList)
{
<li class="group">
<div class="IB left">
<img src="images/user-1.png" alt="" class="stdImg rds50" width="100" height="100" />
</div>
<div class="left brRgt nameAge">
<div class="group">
#saiList.FirstName #saiList.LastName
<div class="age">#saiList.Age<span class="font9">yrs</span></div>
</div>
</div>
<footer class="group">
<div class="sheet brRgt left">
<span class="font9 dblock">present</span>
<div>#Model.Present</div>
</div>
<div class="sheet brRgt left">
<span class="font9 dblock">#Model.Absent</span>
<div>1</div>
</div>
<div class="sheet brRgt left">
<span class="font9 dblock">Model.NoAttendance</span>
<div>1</div>
</div>
<input type="submit" value="Save" id="Save" />
</footer>
Model
public class GuestListForModel
{
public bool Status {get;set;} // arrived or not arrived.
public Int GuestID {get;set;}
}
P.S : I could not get satisfactory answer from googling.
Thanks in Advance
There are two changes that you will need to make:
Change the GuestList action to accept a collection:
[HttpPost]
public ActionResult GuestList(ICollection<GuestListForModel> collection)
{
var temp = collection;
//do your processing
return View();
}
Use a for loop to render the guest list
#for(var i = 0; i < Model.GuestArrivalInfoList.Count; i++)
{
#Html.TextBoxFor(m => Model.GuestArrivalInfoList[i].GuestID)
}
Razor/ASP.NET will take care of both setting the correct id in the view model when rendered (e.g. GuestID would have an id of "GuestArrivalInfoList[1].GuestID"), and will also handle the model binding when hitting the action, making sure that the collection of fields are mapped into the collection.
I presume that there are missing / additional details in your view model and GuestListForModel that ensure that you have the correct data going back and forth (e.g. I don't see the GuestID in the view).
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[MvcApplication1.Models.News]', but this dictionary requires a model item of type 'MvcApplication1.Models.News'.
//my Controller
public class HomeController : Controller
{
CouncilDb _db=new CouncilDb() ;
public ActionResult Index()
{
var News = _db.News
.Take(10);
var Banner = (from r in _db.Banner orderby r.id descending select r).FirstOrDefault();
maz model = new maz();
model.Banner = Banner;
model.News = News.ToList();
return View(model);
}
protected override void Dispose(bool disposing)
{
if (_db != null)
{
_db.Dispose();
}
base.Dispose(disposing);
}
}
public class maz
{
public List<News> News { get; set; }
public Banner Banner { get; set; }
}
//Index view
#model MvcApplication1.Controllers.maz
#{
ViewBag.Title = "Home Page";
}
<!-- Banner -->
<!-- Banner -->
<div id="banner">
<h2> #Model.Banner.H2</h2>
<span class="byline"> #Model.Banner.Span </span>
</div>
#Html.Partial("_News",Model.News )
//Partialview
#model MvcApplication1.Models.News
<!-- Carousel -->
<div class="carousel">
<div class="reel">
<article>
<a class="image featured">
<img src="#Model.ImgUrl " alt="" /></a>
<header>
<h3>#Html.ActionLink(#Model.Title , "serch", "Home")</h3>
</header>
<p>#Model.Body </p>
</article>
</div>
</div>
The .News property of your model is of type List<News> not News so the model declaration in your partial view and the model you are passing to it don't match.
Depending on what you want to acheive, you can either loop through the List inside the index view:
#foreach (var news in Model.News)
{
#Html.Partial("_News", news)
}
or adjust the partial view model declaration and loop there
#model List<News>
....
#for (var news in Model)
{
<article>
<a class="image featured">
<img src="#news.ImgUrl" alt="" /></a>
<header>
<h3>#Html.ActionLink(#news.Title , "serch", "Home")</h3>
</header>
<p>#news.Body</p>
</article>
}
The error is pretty straightforward, once you get past the generic syntax. In C#-speak it's saying this:
The model item passed into the dictionary is of type 'List<News>',
but this dictionary requires a model item of type 'News'.
Your partial view is declared with a #model clause that specifies an item of type News:
#model MvcApplication1.Models.News
but when you pass in data to that partial view, what you're passing in is a List<News>:
#Html.Partial("_News",Model.News)
What you probably want is a loop (a #foreach or similar) that creates one partial view for each element in your News list.
I am trying to build a version of WordPress in MVC4. Currently I am working on the page view.
I've decided that in this view I should also include a menu of all the other pages that have been created.
This is my method for the showPage view:
public ActionResult showPage(string myTitle)
{
var query = from a in db.Pages
where a.title == myTitle
select a;
PageModels item = new PageModels();
item = query.FirstOrDefault<PageModels>();
if (item != null)
{
return View(item);
}
else
{
item.content = "No page with title :" + myTitle + " found.";
return View(item);
}
}
This is my method for the partial I am trying to render:
public ActionResult List()
{
return View(db.Pages.ToList());
}
This is how my view looks like:
#model Dynamic_Web_Pages.Models.PageModels
#{
ViewBag.Title = "Page Preview";
}
#Html.Partial("_ListPartial", new IEnumerable<Dynamic_Web_Pages.Models.PageModels>)
<div class="content">#Html.Raw(Model.content)</div>
Finally this is my partial:
#model IEnumerable<Dynamic_Web_Pages.Models.PageModels>
<div class="dropdown">
#foreach (var page in Model)
{
if(page.parent == 0)
{
<div class="btn-group">
<a class="btn dropdown-toggle" id="#Html.DisplayFor(modelItem => page.id)" role="button" data-toggle="dropdown" data-target="#" href="/#Html.DisplayFor(modelItem => page.title)" >#Html.DisplayFor(modelItem => page.title)
<b class="caret"></b>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="#Html.DisplayFor(modelItem => page.id)">
#foreach (var child in Model)
{
if (child.parent == page.id)
{
<li><a class="child" href="/#Html.DisplayFor(modelItem => child.title)" >#Html.DisplayFor(modelItem => child.title)</a></li>
}
}
</ul>
</div>
}
}
</div>
I get the following error in my view:
Cannot create an instance of the abstract class or interface 'System.Collections.Generic.IEnumerable<Dynamic_Web_Pages.Models.PageModels>'
What should be the second argument of the #Html.Partial be?
Your view accepted a single instance of PageModels
#model Dynamic_Web_Pages.Models.PageModels
#{
ViewBag.Title = "Page Preview";
}
and yet you are passing that in your partial that accepts an IEnumerable and so you got that exception.
Now based on our conversation in your comments, you can load the partial using jquery:
<script>
$("#navmenu").load('#Url.Action("List")');
</script>
where you replace this code:
#Html.Partial("_ListPartial", new IEnumerable<Dynamic_Web_Pages.Models.PageModels>)
// with this
<div id="navmenu"></div>
remove new IEnumerable
and just keep it as
Html.Partial("_ListPartial") in the view
So you should return PartialView instead of view see below code
public ActionResult List()
{
return PartialView (db.Pages.ToList());
}
I have a controller that looks like this:
public class PersonController : Controller
{
public ActionResult Result()
{
var s = new PersonResult();
s = GetPerson(ViewBag.PersonInfo);
return View(s);
}
[...]
}
The controller calls the view Result which looks like this:
#model My.Class.Library.DTO.PersonController
#if (Model != null && Model.Persons.Count > 0)
{
#Html.Partial("Persons", #Model.Persons)
}
So the model can hold many Persons. Persons is sent to its own view like this (view Persons):
#using My.Class.Library.DTO
#model List<Person>
<section>
#foreach (Person person in #Model)
{
#Html.Partial("Person", person)
}
</section>
So I'm sending each Person person to my view Person. And in that view I'm drawing each Person like so:
#model Person
#if (Model.Fields.TryGetValue("description", out description)
{
var descSplit = description.Split('#');
foreach (string s in descSplit)
{
<div class="row-fluid">
<div class="span2">Person</div>
<div class="span10">#s</div>
</div>
}
}
But instead of doing that, I want to pass the string s to its own view. Something like this:
#model Person
#if (Model.Fields.TryGetValue("description", out description)
{
var descSplit = description.Split('#');
<section>
#foreach (string s in descSplit)
{
#Html.Partial("Description", s)
}
</section>
}
But "s" is just a primitive type: a string. How do I pass that to my view "Description"? What should my view "Description" look like? I'm thinking something like this:
#model string
<div class="row-fluid">
<div class="span2"><b>TEST</b></div>
<div class="span10">#s</div>
</div>
But that's not correct... What should my model be and how can I present the string (s) that I'm sending from the other view?
Your code looks right but in your partial view, try using the Model property.
#model string
<div class="row-fluid">
<div class="span2"><b>TEST</b></div>
<div class="span10">#Model</div>
</div>
When you strongly type your Views/PartialViews, you have to use the Model property to read the value you have passed as a Model to this View/PartialView.