An error with displaying multi-level menu - asp.net-mvc-4

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>

Related

Is there a function in Laravel Livewire that allows the value property of a html element to be passed into a function?

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>

Display nested loop in Vue from a GraphQL query

I'm using OneGraph to pull data from Spotify. I can't figure how to render out the 3rd nested loop though even looking at other Vue code samples. I'm trying to return the artist name for each playlist as shown below.
<template>
<ul>
<li v-for="(item, index) in $page.oneGraph.spotify.me.playlists" :key="index">
<ol>
<li v-for="track in item.tracks" :key="track.playlists">
{{track.name}} -
<span v-for="artist in item.tracks.artists" :key="artist.tracks">
{{artist.name}}
</span>
</li>
</ol>
</li>
</ul>
</template>
The query:
{
spotify {
me {
id
playlists(limit: 1) {
name
tracks {
name
artists {
name
}
}
}
}
}
}
Nested loop:
<li v-for="track in item.tracks" :key="track.playlists">{{track.name}}</li>
Child nested loop:
<span v-for="artist in track.artists" :key="artist.tracks" {{artist.name}}</span>

How to keep the tab active? ASP.NET Core Razor Pages

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"

Dynamic menu from database

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.

index of matching items in parent element even if they're in other child containers

I need to get the index of the li.play relevant to the ul.showreel_thumbnails. Is this even possible? All i seem to get is the li index inside ul.row
<ul class="showreel_thumbnails">
<li>
<ul class="row">
<li class="play_video">item</li>
<li class="play_video">item</li>
<li class="play_video">item</li>
</ul>
</li>
<li>
<ul class="row">
<li class="play_video">item 4</li>
<li class="play_video">item</li>
</ul>
</li>
</ul>
so if item 4 is clicked it should give me the index of 4 etc...
best, Dan.
It may not be valid HTML but here's how it would work (with JQuery):
function FindMyCount()
{
var item_count = 0;
$("#showreel_thumbnails li").each(function() {
++item_count;
if($(this).hasClass("igotclicked"))
return false;
});
return item_count;
}
$("#showreel_thumbnails li").click(function() {
$(this).addClass("igotclicked");
var myCount = FindMyCount(); // 1 - the # of li's under the showreel piece
$(this).removeClass("igotclicked");
// Do what you want here.
});