How to keep navbar on ProductList Page - asp.net-mvc

I am working on my MVCOnlineShop, i made on the homepage on the navbar a dropdownlist with categories as dropdown button and products as dropdowncontent, i want to keep this on the ProductList View:
this is my CategoryLayout.cshtml(PartialView):
#model IEnumerable<MVCOnlineShop.Models.Category>
#{
ViewBag.Title = "CategoryLayout";
}
#foreach (var Category in Model)
{
<li>
<div class="dropdown">
<button class="dropbtn">
#Html.ActionLink(Category.CategoryName,
"ProductList", new { Category = Category.CategoryID }, new { #style = "color:#1ABC9C;text-decoration:none;" })
</button>
<div class="dropdown-content">
#foreach (var Product in Category.Products)
{
#Html.ActionLink(Product.ProductName,
"Details", new { id = Product.CategoryID }, new { style = "text-decoration:none;" })
}
</div>
</div>
</li>
}
this is my ProductList.cshtml PartialView:
#model MVCOnlineShop.Models.Category
#{
ViewBag.Title = "ProductList";
}
<script src="~/Scripts/Productjs/bootstrap.min.js"></script>
<script src="~/Scripts/Productjs/jquery.js"></script>
<link href="~/Content/Productcss/bootstrap.min.css" rel="stylesheet">
<link href="~/Content/Productcss/2-col-portfolio.css" rel="stylesheet">
<div class="container">
<!-- Page Header -->
<div class="row">
#foreach (var Product in Model.Products)
{
<div class="col-md-6 portfolio-item">
<a href="#">
<img class="img-responsive" src="#Product.ImageID" alt="">
</a>
<h3>
#Html.ActionLink(Product.ProductName, "Details", new { id = Product.CategoryID })
</h3>
</div>
}
</div>
</div>
and this is how i rendered the CategoryLayout.cshtml in the _Layout.cshtml to show the dropdownlist on the homepage:
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
#Html.Partial("CategoryLayout")
</ul>
</div>
</div>
</div>
Question: how to show this navbar on the ProductList too?
Thanks in advance!

Create a child action:
[ChildActionOnly]
public ActionResult Navbar()
{
var categories = // get categories;
return PartialView("_Navbar", categories);
}
Then, create a partial view to render the navbar (_Navbar.cshtml):
#model IEnumerable<MVCOnlineShop.Models.Category>
#foreach (var Category in Model)
{
<li>
<div class="dropdown">
<button class="dropbtn">
#Html.ActionLink(Category.CategoryName, "ProductList", new { Category = Category.CategoryID }, new { #style = "color:#1ABC9C;text-decoration:none;" })
</button>
<div class="dropdown-content">
#foreach (var Product in Category.Products)
{
#Html.ActionLink(Product.ProductName, "Details", new { id = Product.CategoryID }, new { style = "text-decoration:none;" })
}
</div>
</div>
</li>
}
Then, call the following where you want the navbar to appear:
#Html.Action("Navbar", "Foo")
Where "Foo" is the name of the controller where you added the child action. Then, the view can use whatever model it needs to you and you can still render your navbar with its own model.

If I understood I think what you are looking for is a master page
MSDN says :
ASP.NET master pages allow you to create a consistent layout for the pages in your application. A single master page defines the look and feel and standard behavior that you want for all of the pages (or a group of pages) in your application.
Notice the part saying : standard behavior that you want for all of the pages ...in your application
So what you'll do is rethink your approach. Every element that must appear on every page is to be defined in the master page view.
Please read this MSDN article about creating a master page and child pages
Simply, this is how your master page should be :
<%# Master Language="C#" AutoEventWireup="true" CodeFile="you_file_name.cs" Inherits="Site" %>
<html>
<head>
<asp:ContentPlaceHolder ID="head" runat="server"></asp:ContentPlaceHolder>
<!-- some other elements like scripts, css, etc...-->
</head>
<body>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">#Html.Partial("CategoryLayout")</ul>
</div>
<!-- Here add the code for rendering any other view at will ; for instance ProductList -->
</body>
</html>
Becarefull though : ALL other views that you want to render inside the master page will have to be created accordingly (create view content with master page... and select the appropriate master page on view creation dialog)

Related

How to get the dynamic data of fragment to another page using thymelleaf

I want to get the information(which is dynamically generated) from one html page into another html page.
I used a tag th:fragment in first html page and th:replace in second html page.
But i am getting only static content of first page, is it possible to get the dynamic data or not? can anyone help me please.
Thanks in advance.
Here is my Java code :
#Controller
public class WelcomeController {
#RequestMapping("/")
public ModelAndView usingToList(Model model) {
List<String> colors = new ArrayList<>();
colors.add("green");
colors.add("yellow");
colors.add("red");
colors.add("blue");
model.addAttribute("message", "harika");
model.addAttribute("colors", colors);
List<String> colors2 = new ArrayList<>();
colors2.add("pinkish");
colors2.add("green");
colors2.add("yellow");
colors2.add("red");
colors2.add("blue");
model.addAttribute("coloring", colors2);
ModelAndView mv = new ModelAndView();
mv.setViewName("welcome");
return mv;
}
#GetMapping("/toList")
public String usingToList2(Model model,String color) {
System.out.println("inside uselist");
List<String> colors2 = new ArrayList<>();
if(color.equals("pinkish"))
{
colors2.add("pinkish");
colors2.add("amity");
colors2.add("pimity");
}
if(color.equals("green"))
{
colors2.add("greenish");
colors2.add("amity");
colors2.add("Pretty");
}
model.addAttribute("colors", colors2);
return "welcome";
}
}
Below is my sample POC :
here is my fragment: nav.html which it load the colors dynamically. I am using this side bar fragment in all the pages. When I go another page, data in the side bar is disappering.
<div th:fragment="sidebar2">
<div class="sidebar-sticky pt-3">
<ul class="nav flex-column" id="accordionSidebar">
<li class="nav-item">
<a type="button"
id="collapse"
data-toggle="collapse"
data-target="#collapseExample"
aria-expanded="false" aria-
controls="collapseExample">
<span class="menu-title">Colors List</span>
<span data-feather="plus-circle"></span>
</a>
<div class="collapse" id="collapseExample">
<ul class="nav flex-column sub-menu"
id="collapseExample2">
<li th:each="color :
${coloring}">
<a th:href="#{/toList(color=${color})}"
th:text="${color}"> ></a>
</li>
</ul>
</div>
</div>
welcome.html:
<div th:replace="fragments/nav :: sidebar2"></div>
<main role="main" class="container">
<div class="starter-template">
<h1>Spring Boot Web Thymeleaf Example</h1>
<h2>
<span th:text="'Hello, ' + ${message}"></span>
</h2>
</div>
<ol>
<li th:each="color2 : ${colors}" th:text="${color2}"></li>
</ol>
</main>
When you navigate from one page to another, the Model is empty again (unless you are doing a <form> POST).
When you show the welcome.html Thymeleaf template via usingToList2(), then there is nothing in the Model for the coloring key.
To solve it, also add the coloring key in the usingToList2() controller method.
UPDATE: If all controllers need it, you can use #ControllerAdvice:
#ControllerAdvice
public class GlobalControllerAdvice {
#ModelAttribute("coloring")
public List<String> coloring() {
List<String> colors2 = new ArrayList<>();
colors2.add("pinkish");
colors2.add("green");
colors2.add("yellow");
colors2.add("red");
colors2.add("blue");
}
}
Or if all methods in a single controller need it, you can just add that method in the controller class itself.

How to get descendants from current page in Umbraco 7?

I have a document type with alias dArticlesMain, and for this page I have the following structure.
dArticlesMain
dArticlesCategory1
Article1
Article2
Article3
dArticlesCategory2
Article1
Article2
Article3
dArticlesCategory3
Article1
Article2
Article3
I'm on dArticlesMain and i want to display all the descendants (Articles) and skip it's childrens (dArticlesCategory)
I have this code which display all the childrens (dArticlesCategory) and the descendants (Articles) also when i use the Article properties it's through an error.
<ul>
#foreach(var page in Model.Content.Descendants())
{
<li>#page.Name</li>
}
</ul>
I have got this code but i can't display by Article properties like articleText or articleImage.
<ul>
#foreach(var page in Model.Content.DescendantsOrSelf().OfTypes("Article"))
{
<li>#page.Name</li>
}
</ul>
I have figured it out, and here's my code...
#{
var rootNode = CurrentPage.AncestorOrSelf(1);
var articlesParent = rootNode.Children("dArticlesMain").FirstOrDefault();
<div class="row">
#foreach (var article in articlesParent.Descendants("article").Where("Visible").RandomOrder())
{
<div class="col-sm-6 col-md-3">
<div class="thumbnail">
<a href="#article.Url">
<img src="#article.articlePhoto" alt="#article.articleName" />
</a>
<div class="caption">
<a class="h4" href="#article.Url">#article.articleName</a>
#Umbraco.Truncate(article.articleFullText, 100)
</div>
</div>
</div>
}
</div>
}

Ajax.BeginForm works first time, but calls method twice from second call

Ajax.BeginForm works first time, but calls method twice from second call.. I have referenced all the required scripts.
Firstly, In my main view, I have a common div for two partail views and I am loading respective views based on a radio button selection.
My Select Partial View
<div>
#using (Ajax.BeginForm("GetRandomThirdPartyList", "RandomList", new AjaxOptions { UpdateTargetId = "Contractors" }, new { id = "FORM" }))
{
<div id="Contractors">
<div id="ThirdParty">
<br />
<h3>Third Party Contractors</h3><hr />
<div>Enter High Risk Percentage: #(Html.Kendo().TextBoxFor<int?>(model => model.HighThirdPercent)
.HtmlAttributes(new { style = "width: 50px; height:25px" })
)
</div>
<input type="submit" value="Generate Report" class="k-button btn-primary" id="btn_thirdpaty" />
#* <b>#Html.DisplayFor(model => model.TotHighRisk) HighRisk Employees / #(Html.DisplayFor(model => model.TotLowRisk)) LowRisk Employees</b>*#
</div>
<br />
<div id="ThirdPartytab">
<div id="ReportForm" class="k-content">
<ul id="tabstrip2" class="nav nav-tabs" role="tablist">
<li class="active">HighRisk Third Party Contractors</li>
#* <li style="float:right"><img src="~/Images/icon_ssrs.png" title="Export to SSRS" /></li>*#
</ul>
#*Tab Content Containers*#
<div class="tab-content">
#if (Model.ThirdParty != null)
{
<div class="tab-pane fade in active" id="ThirdPartytab"> #Html.Partial("ThirdParty", Model) </div>
}
</div>
</div>
</div>
</div>
}
My Controller :
int tphigh = 0;
// GET: /RandomList/
[HttpPost]
public ActionResult GetRandomThirdPartyList(VM.RandomList random)
{
// tphigh=Convert.ToInt32(random.HighThirdPercent);
if (random.HighThirdPercent != null)
{
tphigh = Convert.ToInt32(random.HighThirdPercent);
// RedirectToAction("HighRiskCOPL", high);
}
List<VM.RiskList> risklist = (List<VM.RiskList>)AutoMapDomainModel<List<VM.RiskList>>(randomDBentity.GetRandomList(0, 0, tphigh,null));
mainlist.HighThirdPercent = tphigh;
mainlist.ThirdParty = //some list as third party is a Ienumerable
return PartialView("ThirdPartyContractors",mainlist);
}
The form posts properly first time, but from second time, it calls all the code lines in the action method tiwce, sometimes in a haphazard order and finally either populates the grid, or doesnt send any result.
Solved it.. My updatetargetid div was not the parent div..
replaced that..

PagedListPager page always null

This used to work... but now the >> anchor tag of the PagedListPager always passes null to the controller for the page value required...
VS 2013 Web Express & MVC 4 with latest package updates for all.
Just like in Scot Allen's MVC 4 intro, I have a partial view with a PagedListPager
The Controller:
public ActionResult Catalog(string Id= "0", int page=1)
{
var CurrentItemsPage = (get-data-blaw-blaw-blaw).ToPagedList(page,18);
var model = new ShowRoomCatalogPackage(){ CurrentItems = CurrentItemsPage};
return View(model);
}
The catalog page
#model craftstore.Models.ShowRoomCatalogPackage
#{
ViewBag.Title = "Catalog";
Layout = "~/Views/Shared/_Details.cshtml";
}
#using (Ajax.BeginForm("Catalog", "Home", new { category = #Model.SelectedCategoryId, page = 1 },
new AjaxOptions
{
UpdateTargetId = "products",
InsertionMode = InsertionMode.Replace,
HttpMethod = "post"
}
)
)
{
<div class="container" >
<div class="row">
<div class="col-lg-10 col-md-5 col-sm-4 dropdown-menu">
#Html.LabelFor(m => m.SelectedCategoryId)
#Html.DropDownList("id", Model.CategoryItems, new { #id = "ddlCategories", onchange = "this.form.submit();" })
</div>
<div class="col-lg-2 col-md-2 col-sm-1">
#Html.ActionLink("Your Cart", "Index", "ShoppingCart", "", new { #class = "btn btn-green btn-lg" })
</div>
</div>
<div class="row">
#Html.Partial("_CatalogPartial", Model.CurrentItems)
</div><!-- row -->
</div><!-- container -->
}
<br />
<br />
#section Scripts
{
<script type="text/javascript">
new AnimOnScroll(document.getElementById('grid'), {
minDuration: 0.4,
maxDuration: 0.7,
viewportFactor: 0.2
});
</script>
}
The partial view:
#model IPagedList<ShowroomCatalog>
<div id="productList">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="pagedList" data-cs-target="#productList">
#Html.PagedListPager(Model, page => Url.Action("Index", new { category = ViewBag.SelectedCategoryId, page }), PagedListRenderOptions.MinimalWithItemCountText)
</div>
<ul class="grid effect-2" id="grid">
#foreach(var item in Model)
{
var path = String.Format("~/Content/Images/catalog/{0}/{1}", item.OfferType, item.ImagePath);
<li>
<div class="itembox">
<div class="imagebox">
<a href="#Url.Action("Detail", "Home", new { id = item.Id })" title="Detail for #item.CatalogName">
<img class="catalogimg" src="#Url.Content(path)" />
</a>
</div>
<p>#item.CatalogName</p>
</div>
</li>
}
</ul>
</div>
</div><!-- productlist -->
Now the rendered partialview in the browser doesn't have anything in the anchors which may or may not be normal...
<div class="pagedList" data-cs-target="#productList">
<div class="pagination-container"><ul class="pagination"><li class="disabled PagedList-skipToPrevious"><a rel="prev">«</a></li><li class="disabled PagedList-pageCountAndLocation"><a>Showing items 1 through 18 of 65.</a></li><li class="PagedList-skipToNext">»</li></ul></div>
</div>
And when you hover on the >> it doesn't show the page parameter in the URL:
Again, back in the Controller - I get the category (15) but no page parameter or Request.URL parameter is passed to the controller - it's not hiding because of some routing mistake...I think...
How do I get the paging control to work again...???
[EDIT: one more note - the url path on the pager is /controller/action/category/page rather than what shows up on Scot Allen's OdeToFood example where it's equivalent would be /controller/action/category?page=n (like /Home/Catalog/15?page=1 ]
I was missing the JS for the PagedList class anchor element.
var getPage = function () {
var $a = $(this);
var options = {
url: $a.attr("href"),
data: $("form").serialize(),
type: "get"
};
$.ajax(options).done(function (data) {
var target = $a.parents("div.pagedList").attr("data-otf-target");
$(target).replaceWith(data);
});
return false;
};
And this is fired off by :
$(".main-content").on("click", ".pagedList a", getPage);
BUT, this means you need to have your #RenderBody() call in your _Layout.cshtml file wrapped in something with a class of main-content. An example:
<section class="content-wrapper main-content clear-fix">
#RenderBody()
</section>

How to Load Partial Views with Jquery UI Tab by passing parameters?

I have a parent page (DistributionReview.aspx) that has a Deposit Date to select using DatePicker.
Just below I have two tabs(*DistributionByType* and DistibutionByStatus) that I want to load PartialViews. Here the parameter to the PartialView is DepositDate.
And I have a custom ViewModel called DistributionReviewModel that the parent page is implementing.
I am coming across articles that are directly loading static partial views(Ex:
http://www.kevgriffin.com/blog/index.php/2010/02/23/using-jquery-tabs-and-asp-net-mvc-partial-views-for-ajax-goodness/
). But I am looking for any code sample/articles by passing parameter?
Appreciate if anyone can share code samples to pass parameters and load the partialview both when the TabSelection is changed and and DepositDate is changed.
Thanks for your time.
Html Code:
<script type="text/javascript">
$(function () {
//tab
$("#divDistributionReview").tabs();
$("#fileDepositDate").datepicker(); //DateTime Picker
var depositDate = $("#fileDepositDate").val();
});
<div id="container" >
<% using (Html.BeginForm("frmDistributionReview", "DistibutionReview"))
{ %>
<div> Select a Date: <input type="text" id="fileDepositDate" name="datepicker" value='<%= ViewData["FileDepositDate"] %>' /></div>
<div id="divDistributionReview">
<ul>
<li>Distribution Type</li>
<li>Status</li>
</ul>
</div>
<%} %>
</div>
C# Code:
public ActionResult DistributionReview()
{
ViewData["FileDepositDate"] = DateTime.Now.ToShortDateString();
var view = View(ApplicationConstants.DistributionReviewViewName, new MegaLockbox.Web.ViewModels.DistributionByTypeViewModel(securityManager, distributionReviewDataAdapter, Convert.ToDateTime(ViewData["FileDepositDate"])));
return view;
}
public ActionResult DistributionByType(string id)
{
DateTime depositDate;
var view = new PartialViewResult();
if (DateTime.TryParse(id , out depositDate))
{
view = PartialView(ApplicationConstants.DistributionByTypeViewName, new MegaLockbox.Web.ViewModels.DistributionByTypeViewModel(securityManager, distributionReviewDataAdapter, depositDate));
}
return view;
}
public ActionResult DistributionByStatus(string id)
{
DateTime depositDate;
var view = new PartialViewResult();
if(DateTime.TryParse(id, out depositDate) )
{
view = PartialView(ApplicationConstants.DistributionByStatusViewName, new MegaLockbox.Web.ViewModels.DistributionByTypeViewModel(securityManager, distributionReviewDataAdapter, depositDate));
}
return view;
}
here you have nice guide how to do this:
http://ericdotnet.wordpress.com/2009/03/17/jquery-ui-tabs-and-aspnet-mvc/
if you have any questions.. let us know:)
PS you can download the example, and play with it
Html for tab headers
<li><a onclick="LoadTabData('type')" href="/DistributionReview/DistributionByType">Distribution Type</a></li>
<li><a onclick="LoadTabData('status')" href="/DistributionReview/DistributionByStatus">Status</a></li>
Jquery function
function LoadTabData(type){
if(type='type')
$.post("YourController/DistributionByType", { id: $("#fileDepositDate").val()},
function(data) {
$(#"yourByTypeTabDiv").html(data);
});
}else{
$.post("YourController/DistributionByStatus", { id: $("#fileDepositDate").val()},
function(data) {
$(#"yourByStatusTabDiv").html(data);
});
}
Also this will work.
<div id="tabs">
<ul>
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
</ul>
<div id="tab-1">
#Html.Partial("_PartialViewForTab1", Model)
</div>
<div id="tab-2">
#Html.Partial("_PartialViewForTab2", Model)
</div>
<div id="tab-3">
#Html.Partial("_PartialViewForTab3", Model)
</div>
</div>

Resources