Properly Handing Anchors in AngularStrap's ScrollSpy - javascript

How can I properly use AngularStrap's ScrollSpy interface to link to anchors within the current document?
Looking at the AngularStrap documentation I see that when a link is visited a double hash is actually generated. Such as: http://mgcrea.github.io/angular-strap/##scrollspy
However, when implementing the functionality myself I do not see this behavior. In my case the anchor tags are attempting to update the location instead of moving to a location within the current document.
My AngularStrap ScrollSpy resides on a sub-page: my-site.com/#/hig. With the following definition:
<div class="hig-sidebar hidden-print hidden-sm hidden-xs" role="complementary" data-offset-top="-34" bs-affix bs-scrollspy-list>
<ul class="nav hig-sidenav">
<li bs-scrollspy data-target="#overview">
Overview
<ul class="nav">
<li bs-scrollspy data-target="#suboverview">Subsection</li>
</ul>
</li>
<li bs-scrollspy data-target="#accessibility">Accessibility</li>
<li bs-scrollspy data-target="#typography">Color and Typography</li>
<li bs-scrollspy data-target="#graphics">Icons and Graphics</li>
<li bs-scrollspy data-target="#navigation">Navigation Design</li>
<li bs-scrollspy data-target="#elements">UI Elements</li>
<li bs-scrollspy data-target="#reference">Reference</li>
</ul>
<a href ng-click="gotoTop()">Back to top</a>
</div>
As I scroll through the document, the ScrollSpy properly highlights the current section. But when I click on a link, for example the Color and Typography link, it updates the URL to: my-site.com/#typography.
I've been looking at the AngularStrap code and can't see what I haven't done that it is doing. How can I make sure the anchor link adds to the #/hig instead of replacing it?

Yes, as I have explained here:
https://github.com/mgcrea/angular-strap/issues/573
In Angularjs the anchor links like Overview do not work when you have $routeProvider for configuring your routing.
You can fixed this by replacing the anchor links with a controller, as follows:
controller:
$scope.scrolltoHref = function (id){
// set the location.hash to the id of
// the element you wish to scroll to.
$location.hash(id);
// call $anchorScroll()
$anchorScroll();
};
HTML:
Overview

Given the way you talk about "update the location", i think that you may be using the scroll spy within an ngView directive. In this case, check out the workaround described at the beginning of this issue:
https://github.com/mgcrea/angular-strap/issues/573
This helped me to have a kind of working solution, with minor offsets issues

Related

How to scroll to a component from another component in Angular?

I've been hours, even a couple of days trying to get this done but i can't find a solution, I've tried everything but haven't found a case like mine.
I'm trying to scroll to another component in my one-page website from a navbar, which is another component. The main app component I set like this:
<body>
<app-navbar></app-navbar>
<app-page-one id="page-one"></app-page-one>
<app-page-two id="page-two"></app-page-two>
<app-page-three id="page-three"></app-page-three>
<app-footer></app-footer>
</body>
As you can see i put an id on each component so i could identify it when trying to scroll.
I want to click the Page Three button inside my navbar for it to scroll down to the page three component. My navbar component looks like this:
<body class="body">
<header class="header">
LOGO
<div class="menu-toggle">
<fa-icon [icon]="faBars" transform="grow-20"></fa-icon>
</div>
<nav class="nav">
<ul>
<li>
Page One
</li>
<li>
Page Two
</li>
<li >
Page Three
</li>
</ul>
</nav>
</header>
</body>
I've tried using Ngx Page Scroll and everything, but can't seem to make it work. I'm not sure if I need to use Input Output to make them communicate or something like that, anything will help, thanks.
you can use angular router fragment or the angular cdk for scrolling.
I find the angular router is the easiest, but I will give you the link for the angular cdk in case you don't like this way.
first thing on index.html declare a style tag - because without it smooth scrolling won't smooth scroll.
index.html
<style>
html {
scroll-behavior: smooth;
}
</style>
you can change the scroll offset as you see fit
app-router.module.ts
imports: [RouterModule.forRoot(routes, {scrollPositionRestoration: 'enabled',
anchorScrolling: 'enabled',
scrollOffset: [0, 64]})]
then your component.ts
<li>
<a routerLink="." fragment="page-one" >Page One</a>
</li>
<li>
<a routerLink="." fragment="page-two">Page Two</a>
</li>
<li >
<a routerLink="." fragment="page-three">Page Three</a>
</li>
edit your component.css
a{
cursor: pointer
}
you can also do this to scroll to fragments on other views. https://angular.io/api/router/RouterLink
you might need to add a # on each fragment which is better than id #page-two as an example. and you would change the fragment to reflect that. the cdk way is in this link https://material.angular.io/cdk/scrolling/overview
Each href needs to have a reference to what element.id you want ngx-page-scroll to move the viewport to. Therefore the body should be something like this.
<li>
Page One
</li>
<li>
Page Two
</li>
<li >
Page Three
</li>
If you refer to the npm page and look at the url, https://www.npmjs.com/package/ngx-page-scroll#usage. You can see there is both a link and an element reference(#usage) to the Usage section (id="usage") of the documentation.

Adding class to primary-nav link when on a sub-page based on the url

I have primary navigation that are just "in-page" links on the home page. I also have a section of three pages for pricing that live as sub-pages with the urls: /pricing/basic-pricing.html, /pricing/pro-pricing.html and /pricing/pricing-premium.html.
On those three pages, I have a side-nav to get back-and-forth between those pages. So two navigation elements (primary-nav and side nav). When on a sub-page i.e. /pricing/basic-pricing.html, I would like the primary-nav link called "pricing" to have an active class.
I have it working with the code below, but was wondering if there is a better way in case I add more sub-pages in the future. I don't want to have to add more jQuery just to accommodate a new page. Right now it's only looking to see if the url contains the string 'pricing' in the href and then it adds the class to the 'pricing' link in the primary nav.
<nav class="primary-nav">
<ul class="menu collapse vertical large-horizontal">
<li>features</li>
<li>options</li>
<li>pricing</li>
<li>testimonials</li>
<li>contact</li>
</ul>
</nav>
<ul class="vertical menu side-nav">
<li>Basic Pricing</li>
<li>Pro Pricing</li>
<li>Premium Pricing</li>
</ul>
$(document).ready(function () {
$('.side-nav.menu a.is-active[href*="pricing"]').each(function () {
$('.primary-nav .menu a[href$=pricing]').addClass('is-active');
});
});
you can use location global object to detect which url or uri you're in,
here a link t it documentation : link
example:
console.log(location.pathname)
// /questions/56091860/adding-class-to-primary-nav-link-when-on-a-sub-page-based-on-the-url
in you case
// /pricing/basic-pricing.html

Get reference to object without a unique attribute

I'm trying to get the reference of this particular part of the page, then I can use the method click() on it. I was trying to use a CSS selector like this:
var customersMenu = $('input[translate=menu.customers]');
But no success until now. Can you help me anyway?
<ul class="menu">
<li ui-sref-active="active">
<a class="ng-scope" translate="menu.home" href="#/home">Home</a>
</li>
<li ui-sref-active="active">
<a class="ng-scope" ui-sref="customer.list" translate="menu.customers" href="#/customers">Customers</a>
</li>
</ul>
First of all, you might need to open up the menu to be able to click the menu item:
var menu = $("ul.menu"); // $ is a shortcut to element(by.css("selector"))
menu.click();
Then, the easiest way to locate the menu item would be "by link text":
menu.element(by.linkText("Home")).click();

.first() element not working with dynamic generated <li>

I think I am missing some minor concept here, but have done enough googling to find that but no use. Hence posting on this forum seeking some help.
I am generating navigation tab dynamically using this code:
<div class="tabbable">
<ul class="nav nav-tabs" id="testing">
<li ng-repeat="storageOption in gridOptions[$index].ownedJay" class=""><a href="#c{{storageOption.StorageHostname}}" >Data{{storageOption.StorageHostname}}</a></li>
</ul >
In above code, class is left blank. Above code can create many li based on number of elements in storageOption (ng-repeat).
But I want to add class "active" in first li only.
For that I have added following code in the script section of same page:
$(".tabbable ul li").first().addClass("active");
But above code is adding active class in all the li generated.
Can anyone please let me know where I am missing here.
Thanks in advance.
You need to do it in angular way, as angular does provided that option by ng-class that basically need expression like ng-class="{'class': expression}".In ng-class expression you could use $first that tells you its first element of ng-repeat or not, and use ng-href instead of href.
Markup
<li ng-repeat="storageOption in gridOptions[$index].ownedJay" ng-class="{'active': first}">
<a ng-href="#c{{storageOption.StorageHostname}}" >Data{{storageOption.StorageHostname}}</a>
</li>
Alternative
If you want to make active togglable then you could simply maintain one flag that will have the information of which li is selected.
<ul class="nav nav-tabs" id="testing" ng-init="selected=0">
<li ng-repeat="storageOption in gridOptions[$index].ownedJay"
ng-class="{'active': $index == $parent.selected}"
ng-click="$parent.selected == $index">
<a ng-href="#c{{storageOption.StorageHostname}}" >
Data{{storageOption.StorageHostname}}
</a>
</li>
</ul >
In above markup I used $index but you could unique thing if you have it you ng-repeat array.
$(".tabbable").find('li:nth-child(1)').addClass("active");
Try using a different selector to select the first li
FIDDLE
You can use ng-class attribute to check if the $index is 0 then add class active.

Navigation with onClick / Javascript not working

I have created a menu for my website which you can find here:
http://jsfiddle.net/nq9Nt/9/
When click a category on the menu it opens that category on my main navigation?
Is something conflicting or have I placed my Javascript in the wrong place?
So I want to be able to click a category and show the sub-categories but it just won't work. Also is there a way to keep open the category you clicked after you change page?
Thank you
<ul class="nav">
<li>Category 1
</li>
<li class="drop">Category 2
<ul id="sub1">
<li>Item
</li>
<li>Item
</li>
</ul>
</li>
<li class="drop">Category 3
<ul id="sub1">
<li>Sticker
</li>
<li>Sticker
</li>
</ul>
</li>
<li>Category 4
<ul id="sub1">
<li> Mural
</li>
<li>Mural
</li>
</ul>
</li>
$(".drop")
.on('click', function () {
$(this).find('ul').toggle();
})
Actually at least on jsfriddle animation works and if you replace href of your anchors from '#' to a real url you will be redirected to another page, so first make sure that you've attached jquery library in head of the document (since you use it in your script), then move your script to the bottom of the page, right before tag 'body' closes.
About keeping the state of the opened categories after refresh - usually it is made on server side while generating template by adding class, for example 'active', to current link and then, using css, corresponding category (or a hierarchy of categories) is set to be opened (li.active ul {display: block;} for example). Well, actually you could do the same trick - use js to find out current url with the help of window.location.pathname value and match it with a href value of your navigation links and then assign class 'active' to the found element (or its parent, it is up to your css)
You can add a class drop to li in 4th Category, so it will work as others. And remove that onclick if you don't plan to use it.
http://jsfiddle.net/nq9Nt/10/
Here the example,
jsbin
You have gave the anchor href with #, So It reloads the page. And also you have gave the onclick method, But it doesn't there.

Categories

Resources