Dropdown menu dynamically "generated" from Umbraco backend possible? - razor

I am trying to populate my header with links. I have two dropdowns at the moment. I would like to populate the links using Umbraco and Razor, so nothing is hardcoded. This can be done quite easily (see code below), but populating the dropdowns is the tricky part.
I'm not sure how I would populate the dropdown in a good way. They are not subpages or anything like that, but they are simply dropdowns to make the header less wide. Here's how I populate my header using Razor by grabbing the links in Umbraco:
var home = CurrentPage.Site();
#foreach (var item in home.Children.Where("Visible"))
{
<li class="#(item.IsAncestorOrSelf(CurrentPage) ? "active" : null)">
#Umbraco.GetDictionaryValue(item.Name)
</li>
}
home.Children.Where("Visible") is simply grabbing all the child pages, where I have not checked the umbracoNaviHide.
This is currently how my header is created NOT using Umbraco (which I need to populate using the pages from Umbraco):
<nav class="navbar navbar-toggleable-lg navbar-light fixed-top">
<div class="d-flex align-items-center justify-content-between">
<button class="navbar-toggler navbar-toggler-left" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand ml-3" href="/en">
<img src="logo.png" class="logo" alt="logo">
</a>
</div>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto justify-content-between full-width">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
About
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="#">About Us</a>
<a class="dropdown-item" href="#">History</a>
</div>
</li>
<li>
Our Products
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href id="navbarDropdownMenuLink2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Resources
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink2">
<a class="dropdown-item" href="#">Tips</a>
<a class="dropdown-item" href="#">News</a>
</div>
</li>
<li>
Contact Us
</li>
</ul>
</div>
</nav>
This will produce a result like this: https://codepen.io/anon/pen/QvyeRm
I don't want any of the links to be affected by this, as the links or pages doesn't really have anything to do with the header's layout. Here are some example URLs:
/en/about-us/
/en/history/
/en/our-products/
/en/tips/
I hope that makes sense.
Is there a good and easy way to do this?

There are a few ways that you could do this. the way I typically do main navigation on a site is to have a multiple content picker or similar to alow me to choose the items I want to show up in the navigation.
In your example, your sub-menu items aren't actually underneath the parent menu item. You could create a picker for each of the dropdowns, say on your home node, and choose the pages for each one?
If you plan to make the navigation more flexible though, you might need to do something a bit fancier, you could look at something like the Nested Content package to help you do this?

So I found a pretty good way of doing this. All I need to create is a content with document type set to Dropdown, then set the title (basically the label) and then add permissions for the children of the dropdown.
#foreach (var item in selection)
{
if (item.GetPropertyValue<bool>("showDropdown"))
{
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
#item.GetVortoValue("Title")
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
#foreach (var child in item.Children)
{
<a class="dropdown-item" href="#child.Url">#child.GetVortoValue("Title")</a>
}
</div>
</li>
}
else
{
<li>
#item.GetVortoValue("Title")
</li>
}
}
I started by creating a document type called "Dropdown". The sole purpose of this document type, is to be a parent for the pages inside the dropdown. Then I set the permissions to allow the two pages I have to be inside the dropdown, and I set the permissions on my Master to allow the dropdown document type.
Then I created a new property on the master document type, which is called "Show dropdown". If this is ticked, it will show the dropdown on the page. I had to do this, because pages with children (if(item.Children.Any())) would be true no matter what.

Related

import or including navbar into different file pages with dynamic active nav tab

I just want to ask if there's a way to store my navbar in one file page and dynamically change its active depending on what user will click?
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Disabled</a>
</li>
</ul>
</div>
</nav>
Like this code, it will be stored in one page. But the home should not be active if clicked on features and features should be the active item. Because I am copying the same navbar into every pages, and changing its active depends on the file page. I want to do this to avoid redundancy, if possible. Thank you.
You can use Javascript to gather all of the <a> elements from your navbar by their class, in this case your nav-link class will do. With a collection of these links, we can then iterate through them and check to see which target href matches the current page the user is on, and append text to the end of it.
You can place the following code block just before your closing body tag.
<script>
$(document).ready(function() {
let allLinks = $(".nav-link").map(function() {
return this; // Fetch all elements that have the .nav-link class and add them to our list.
}).get();
// Iterate through each of the links we fetched.
$.each(allLinks, function(key, value) {
if (value.href == document.URL) { // If the href attribute for this link matches the current page URL.
$(this).html(value.innerText + " <span class='sr-only'>(current)</span>"); // Adjust the HTML of the element and append a suffix to the end, or do anything else here as required.
}
});
});
</script>

How do I change the color of my dropdown text (Bootstrap)

I am new to bootstrap and I used a template to help me develop a nav bar for mu website, but I am confused on how to style the nav bar using a seperate CSS doc. Specifically, my toggle for the dropdown won't change color. I tried to set as many elements to color:black but they never actually effected the dropdown toggle text. The only way I could change the color was through the tag in html (I had to use the style:"color:black;") and still it wouldn't change back to white on hover like the other elements. Does anyone know what I'm doing wrong. I also wanted to add an onclick animation if anyone could help me with that as well. This is the template I used
<nav class="navbar navbar-expand-lg navbar-custom">
<a class="navbar-brand" href="#"> <span> Artemis Server Hosting </span> </a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#basicExampleNav"
aria-controls="basicExampleNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="homepageNav">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home
<span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="features.html">Features
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="pricing.html">Pricing
</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">idk</a>
<div class="dropdown-menu dropdown-primary" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="#">yet</a>
</div>
</li>
</ul>
<img src="https://cdn4.iconfinder.com/data/icons/shopping-21/64/shopping-01-512.png" style="align:center;" height="3%" width="3%" href="cart.html">
</div>
</nav>
.navbar-brand {
color: white;
}
.navbar-brand:hover {
color: black;
}
.nav-link {
color: black;
}
.nav-link:hover {
background-color: black;
color: white;
border-radius: 8px;
}
So first of all, to make your last li to a cursor:pointer you have two options:
Either put href="#"into the <a> tag, like: <a href="#" class="nav-link dropdown-toggle" ...</a> or you use this property in the css: a:hover { cursor: pointer }
To color your dropdown black try this:
.dropdown-menu > a {
background-color:black;
color:white;
}
About your animation: please be a little more specific what sort of animation you want, like change the whole background color, show or hide something or whatever, but in general, if you use jQuery, you can do the following. The excample code shows an alert box
$(".navbar-toggler").on("click", function() {
alert("Hello");
});
Please note, that this code fires if someone clicks on any navbar-toggler button on your website - if you have multiple ones, all of the will fire it! If you only want to fire it when someone click a specific dropdown toggler, you should give it an id and do $("#your_id"). instead of $(".navbar-toggler").
if you don't use jQuery, the easiest would be to assign an onclick event to your button:
<button class="navbar-toggler" [...] onclick="doSomething()">
and then write your JavaScript function doSomething() that does whatever you want it to do.
If you tell me what animation you want to trigger I might be able to tell you a little bit more. (Also, as a side note: you should ask only one question per post. That's how Stack Overflow works and you'll get answers faster)

Strange effect in data-toggle

I have a bootstrap navbar in my site but when it is shown collapse, if click on a link the menu does not close, and I would like navigate to the page and the menu will also be closed.
I've added
data-toggle="collapse" data-target="#navbarNav"
And do the trick, but the link have a strange effect when is not collapse (in a desktope mode)
I create a fiddle:
http://jsfiddle.net/soyjuanmedina/rscdu7gv/3/
An add the code to the link 'Home' and you can see (you need to expand the result window to see the menu not collapsed) and see when click in it the words disappear to appear again
This is happening because the menu when on desktop doesn't dissapear it just changes its layout so it will still try and collapse it.
If you just need a fix for this and don't mind it being a bit messy, here's what I came up with.
Have two elements, one that will be visible on mobile and one that will be visible on desktop like this (pay attention to the classes)
Mobile:
<a class="nav-link d-block d-md-none" href="#" data-toggle="collapse" data-target="#navbarSupportedContent">
Home
</a>
Desktop:
<a class="nav-link d-none d-md-block" href="#">
Home
</a>
So final result would be:
<li class="nav-item active">
<a class="nav-link d-none d-md-block" href="#">
Home
</a>
<a class="nav-link d-block d-md-none" href="#" data-toggle="collapse" data-target="#navbarSupportedContent">
Home
</a>
</li>

PrimeNg confirmDialog make changes on my navbar

My navbar works really well and it is fully responsible, but when I open confirm dialog in background my navbar width goes to 800px even if screen has 1480px making an empty space on the right side like you can notice on the screen.
I really don't have idea how to fix it, this is my navbar:
<nav class="navbar navbar-expand-md navbar-dark bg-dark">
<a class="navbar-brand" routerLink="">frontend</a>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link menu-item dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Vehicles</a>
<div class=" dropdown dropdown-menu">
<a class="dropdown-item menu-item" routerLink="/topic"> Vehicles list </a>
<a class="dropdown-item menu-item" routerLink="/add-topic"> Add vehicle </a>
</div>
</li>
</ul>
</div>
</nav>
<router-outlet></router-outlet>
I use default confirm dialog from primeNg without any changes:
confirm dialog
Maybe I could somehow make additional css to navbar to make position allways on 100% of screen? Any ideas how could I do that?
You are using bootstrap navbar and primeng so some css are getting conflict. If you write below css in style.css so navbar working normal.
.ui-overflow-hidden {
position: unset !important;
}

How do I indicate an active nav-item in a common header?

I have a header that I plan to use on the top of all my pages. I'd like to keep it in a separate file (something I'm used to doing with php, but I'm new to the world of Bootstrap); however, I am not sure how I would handle dynamically assigning the active class to the nav-item that represents the current page. Does Bootstrap (4) have a baked-in solution for this sort of thing? I've been searching around but haven't found a good solution yet. Thanks in advance!
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light bg-transparent fixed-top">
<div class="container">
<a class="navbar-brand" href="#">My Site</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home
<span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Work</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Blog</a>
</li>
</ul>
</div>
</div>
</nav>
Bootstrap includes some jQuery and is not just CSS. However, you can always run some JavaScript or jQuery on page load that toggles the class based on reading an element when the page is loaded. For example you could:
1) have an identifier on each page (eg. class name inside an element on a page that holds the page's name/value). Example:
<h1 class="page-lookup">
Home
</h1>
2) set you jQuery in a function to read for class and grab the value of the element with a .val(). Example:
const activePage = $(".page-lookup").val()
3) Add an id on each in your navbar to uniquely identify them. Example:
<li id="home-page" class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
4) Run a switch case that looks up the stored value (activePage) for a match. In the case that matches you can run jQuery to update the class to include the "active" syntax that will trigger Bootstrap's formatting.
Example:
switch (activePage) {
case Home:
$('#home-page).attr("class", "nav-item active");
break;
case About:
$('#about-page).attr("class", "nav-item active");
break;
}