I have a Login page where on login it takes user to Home Page where dynamic menu is loaded.The problem is that when a user clicks on one of the menulink the loaded menu is not visible
This is because I have written the code inside Index action of theHome controller.
So my question is where should I write the logic for dynamic menu so that it is accessible on clicking the menulink.
_Layout.cshtml file where menu is loaded
#model SMS.Models.ViewModel.DashboardVM
#if (Model != null && Model.MenuParentList.Count > 0)
{
<!-- Sidebar Menu -->
<ul class="sidebar-menu">
<li class="header">MAIN NAVIGATION</li>
<li class="active">
<a href="#">
<i class="fa fa-dashboard"></i> <span>Dashboard</span>
</a>
</li>
#foreach (var parentItem in Model.MenuParentList)
{
<li class="treeview">
<a href="#">
<i class="fa fa-th"></i>
<span>#parentItem.MenuParentName</span>
<i class="fa fa-angle-left pull-right"></i>
</a>
<ul class="treeview-menu">
#Html.Partial("_MenuParent", Model.MenuList.Where(x => x.ParentID == parentItem.MenuParentID))
</ul>
</li>
}
</ul>
}
Logic for dynamic menu goes here
public ActionResult Index()
{
var _dashboardVM = new DashboardVM
{
User = _employee.Users.FirstOrDefault(),
MenuParentList=_db.Menus
.Where(x => _parentList.Contains(x.Id))
.Select(x => new SMS.Models.ViewModel.DashboardVM.MenuParent
{
MenuParentID = x.Id,
MenuParentName = x.MenuName
})
.OrderBy(x=>x.MenuParentID)
.ToList(),
MenuList=_employee.Designation.Role.MenuRoles
.Select(x=>x.Menu)
.ToList()
};
}
Create a separate [ChildActionOnly] method that generates your menu and call it from the layout page so its available in all pages
[ChildActionOnly]
public ActionResult Menu()
{
var model = new DashboardVM
{
....
}
return PartialView("_Menu", model);
}
and create a _Menu.cshtml partial view to generate the html
#model DashboardVM
....
and then in your layout, remove #model SMS.Models.ViewModel.DashboardVM (a layout should not have a model unless that model is a base class for all models used by the layout) and then include
#Html.Action("Menu", yourControllerName)
which will call the Menu method and insert the partial view it returns into the layout.
Related
Is there a function in Laravel Livewire that allows the value property of a html element (be it a radio button, checkbox, dropdown list or textbox) to be passed into a function?
For example: I have on a page a list. This list consists of different cooked dishes. I select a dish from the list by clicking on it and the value passed. Can this value be passed into a function?
LiveWire Controller
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Dishes extends Component
{
public function showRecipe($value)
{
//query database or some conditional logic
}
public function render()
{
return view('livewire.dishes')
}
}
LiveWire Component
<div>
<ul>
<li value="pizza" wire:click="showRecipe(this.value)">Pizza</li>
<li value="cherry_pie" wire:click="showRecipe(this.value)">Cherry Pie</li>
<li value="beef_stronganoff" wire:click="showRecipe(this.value)">Beef Stroganoff</li>
<li value="caesar_salad" wire:click="showRecipe(this.value)">Caesar Salad</li>
<li value="lobster_newburg" wire:click="showRecipe(this.value)">Lobster Newburg</li>
</ul>
</div>
value is not a valid attribute on an <li> tag. However, you can put an anchor-tag with a "prevent default" action it, or just keep the wire:click on the li and pass the data directly to the method.
<div>
<ul>
<li wire:click="showRecipe('pizza')">Pizza</li>
<li wire:click="showRecipe('cherry_pie')">Cherry Pie</li>
<li wire:click="showRecipe('beef_stronganoff')">Beef Stroganoff</li>
<li wire:click="showRecipe('caesar_salad')">Caesar Salad</li>
<li wire:click="showRecipe('lobster_newburg')">Lobster Newburg</li>
</ul>
</div>
If you generate this in a loop with PHP/blade, you should use wire:key on it. The key should be something unique, so Livewire can keep track of each individual record.
<div>
<ul>
#foreach([
'pizza' => 'Pizza',
'cherry_pie' => 'Cherry Pie',
'beef_stronganoff' => 'Beef Stroganoff',
'caesar_salad' => 'Caesar Salad',
'lobster_newburg' => 'Lobster Newburg',
] as $value=>$name)
<li wire:key="dish-{{ $loop->index }}" wire:click="showRecipe('{{ $value }}')">{{ $name }}</li>
#endforeach
</ul>
</div>
Hi there,
I have a problem with my tabs in navbar.
The result I wish:
See the "Home" tab class active by default
Clicking on another tab must to remove active class from the <a> that is already active (at the starting point it is "Home" tab)
Add the same class active to the tab I click on (which also mean that app redirects me)
Keep the clicked tab active
What I've got so far:
I see the "Home" tab set active by default
Clicking on any tab removes class active as I mentioned above and adds the same class to the clicked tab
Redirection happens and "Home" tab returns its default state (becomes active again)
I share my code below:
HTML
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse" id="navigation">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link active" id="home" asp-area="" asp-page="/home/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" id="declarations" asp-area="" asp-page="/declarations/Index">Declarations</a>
</li>
<li class="nav-item">
<a class="nav-link" id="topics" asp-area="" asp-page="/topics/Index">List of Topics</a>
</li>
<li class="nav-item">
<a class="nav-link" id="contacts" asp-area="" asp-page="/contacts/Index">Contacts</a>
</li>
<li class="nav-item">
<a class="nav-link" id="faq" asp-area="" asp-page="/faq/Index">FAQ</a>
</li>
</ul>
</div>
jQuery
$("#navigation .navbar-nav a").click(function() {
$("#navigation .navbar-nav").find("a.active").removeClass("active");
$(this).addClass("active");
localStorage.className = "active";
});
$(document).ready(function() {
stayActive();
});
function stayActive() {
$(this).children().addClass(localStorage.className);
}
Since you are using Razor page, everytime user clicks on a tab, the page will be rendered again on server and then sent back. Therefore I suggest that we set the active class on serverside based on the current route.
Add a new HtmlHelper class
public static class HtmlHelperExtensions
{
public static string ActiveClass(this IHtmlHelper htmlHelper, string route)
{
var routeData = htmlHelper.ViewContext.RouteData;
var pageRoute = routeData.Values["page"].ToString();
return route == pageRoute ? "active" : "";
}
}
Go to your _ViewImports.cshtml and add this import.
Without this, it will not recognize the helper we're about to add in step 3.
#using <Namespace of the class you wrote in step 1, if not already here>
Then your cshtml will be
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse" id="navigation">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link #Html.ActiveClass("/home/Index")" id="home" asp-area="" asp-page="/home/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link #Html.ActiveClass("/declarations/Index")" id="declarations" asp-area="" asp-page="/declarations/Index">Declarations</a>
</li>
...Same for 3 other tabs, make sure that the route you pass in ActiveClass method
...must be the same as the route in asp-page
...If you're afraid of duplication, make some static class to store these routes as constants
</ul>
</div>
In addition to #Nam Le answer I suggest complete solution.
I've found the way how can we use the exception properly.
First of all, as we set active class on serverside based on the current route, we have to add asp-route-routeId="{routeId:int}" in the cshtml we work with.
Secondly, use this jQuery code:
jQuery
$("#navigation .navbar-nav a").click(function() {
$("#navigation .navbar-nav").find("a.active").removeClass("active");
$(this).addClass("active");
localStorage.className = "active";
});
$(document).ready(function() {
stayActive();
});
function stayActive() {
$(this).addClass(localStorage.className);
}
And the last step is to setup "launchUrl": "route/routeId" in the launchSetting.json file to run the application with certain route. This action make our HtmlHelper extension react and add active status to the tab we want.
Hope that here is no any gross mistakes in the solution I suggest :)
UPD: don't forget to add route in cshtml #page "/route/routeId"
I am working on a Asp.net core 2.2 project and use ReflectionIT.Mvc.Paging package for paging.
Every thing is ok but i want to change paging style in my view.
Here is code to use Pager view component
<nav>
#await this.Component.InvokeAsync("Pager", new { PagingList = this.Model })
</nav>
And here is paging pic :
I want to write First And Last instead of 1 And 15 in above pic and want to change some css styles.
You can also create your own Pager view if you want to. You store it in the folder Views\Shared\Components\Pager :
You can for instance call the AddPaging method which you can use to set the PagingOptions. This allows you to specify which View is used for the Pager ViewComponent , in ConfigureServicesfunction :
// Register ViewComponent using an EmbeddedFileProvider & setting some options
services.AddPaging(options => {
options.ViewName = "Bootstrap5";
options.HtmlIndicatorDown = " <span>↓</span>";
options.HtmlIndicatorUp = " <span>↑</span>";
});
Modify the Bootstrap5.cshtml to fit your requirement :
#model ReflectionIT.Mvc.Paging.IPagingList
#* Fake Boostrap 5 based pager *#
#{
var start = this.Model.StartPageIndex;
var stop = this.Model.StopPageIndex;
}
#if (this.Model.PageCount > 1) {
<ul class="pagination pagination-sm justify-content-end">
#if (start > 1) {
<li class="page-item">
<a href="#Url.Action(Model.Action, Model.GetRouteValueForPage(1))" aria-label="First" class="page-link">
<span aria-hidden="true">First</span>
</a>
</li>
}
#if (this.Model.PageIndex > 1) {
<li class="page-item">
<a href="#Url.Action(Model.Action, Model.GetRouteValueForPage(this.Model.PageIndex - 1))" aria-label="Previous" class="page-link">
<span aria-hidden="true">«</span>
</a>
</li>
}
#for (int i = start; i <= stop; i++) {
<li class="page-item #((Model.PageIndex == i) ? "active" : null)">
#if (i == 1)
{
#Html.ActionLink("First", Model.Action, Model.GetRouteValueForPage(i), new { #class = "page-link" })
}
else{
#Html.ActionLink(i.ToString(), Model.Action, Model.GetRouteValueForPage(i), new { #class = "page-link" })
}
</li>
}
#if (this.Model.PageIndex < this.Model.PageCount) {
<li class="page-item">
<a href="#Url.Action(Model.Action, Model.GetRouteValueForPage(this.Model.PageIndex + 1))" aria-label="Next" class="page-link">
<span aria-hidden="true">»</span>
</a>
</li>
}
#if (stop < this.Model.PageCount) {
<li class="page-item">
<a href="#Url.Action(Model.Action, Model.GetRouteValueForPage(this.Model.PageCount))" aria-label="Last" class="page-link">
<span aria-hidden="true">Last</span>
</a>
</li>
}
</ul>
}
Output :
Try this one
services.AddPaging(options => {
options.ViewName = "Bootstrap4";
options.HtmlIndicatorDown = " <span>↓</span>";
options.HtmlIndicatorUp = " <span>↑</span>";
});
I'm trying a multi-level menu in mvc4.
When I run the code, main children of my menu and also their main children are displayed correctly
but at third level, the following menus display over each other
what should I do?
here is my code:
#helper getmenutree(int? parentId)
{
foreach (var item in Model.Where(p => p.ParentId == parentId))
{
<li>
#item.Name
<ul>
#if (item.Groups1.Any())
{
#getmenutree(item.Id)
}
</ul>
</li>
}
}
<nav id="main_nav">
<ul>
#getmenutree(null)
</ul>
</nav>
I have users list and want to bind that on top navigation bar, this will always visible for many pages, how i can bind it, i don't want to add code on each file, is there any method in mvc4 that is called for each view?
My view:
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
Name Three<b class="caret"></b>
<ul class="dropdown-menu">
//Here i want to show data dynamically, data can be in collection.
<li>Name one</li>
<li>Name two</li>
<li>Name Three</li>
<li>Four</li>
</ul>
</li>
</ul>
</div>
Controller:
ICollection<Names> names = this.obj.GetNames();
In situations like this I prefer to use a code behind call to the view bag. try something like this
#Html.DropDownList("Action", PathToController.GetUsers())
then on the controller where you want to put this method
public static List<SelectListItem> GetUsers(){
List<SelectListItem> ls = new List<SelectListItem>();
var result = //database call here
foreach(var temp in result){
ls.Add(new SelectListItem() { Text = temp.Name, Value = temp.ID });
}
return ls;
}