Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Responsive navbar #738

Closed
ravipunjwani opened this issue Sep 15, 2016 · 30 comments
Closed

Responsive navbar #738

ravipunjwani opened this issue Sep 15, 2016 · 30 comments

Comments

@ravipunjwani
Copy link

ravipunjwani commented Sep 15, 2016

Hi guys,
This library is just an awesome box to start with angular while dependent on bootstrap css. I'm creating a navbar and just got through an issue here. Probably it's a new-feature request or it can be said as a bootstrap-feature not yet in ng-bootstrap.

Feature description:

Look at this link where you can set collapsible navbar based on the size of the screen.
Bootstrap 4 documentation for navbar

This can be seen in responsive navbar section of this link. To the point, it actually uses navbar-toggleable-xs class to define this functionality. The navbar comes collapsible only when the screen size is xs, otherwise, its a regular navbar.

Version of Angular, ng-bootstrap, and Bootstrap:

Angular2: 2.0.1

ng-bootstrap: 1.0.0-alpha.6

Bootstrap: 4.0.0-alpha.4

@jnizet
Copy link
Member

jnizet commented Sep 15, 2016

Hi @ravipunjwani

We already have the NgbCollapse directive to do that. Replace the bootstrap example by the following snippet, and you'll have the equivalent.

Is there something more needed?

<nav class="navbar navbar-light bg-faded">
  <button class="navbar-toggler hidden-sm-up" type="button" (click)="isNavbarCollapsed = !isNavbarCollapsed" aria-controls="exCollapsingNavbar2" aria-expanded="false" aria-label="Toggle navigation">
    &#9776;
  </button>
  <div [ngbCollapse]="isNavbarCollapsed" class="collapse navbar-toggleable-xs" id="exCollapsingNavbar2">
    <a class="navbar-brand" href="#">Responsive navbar</a>
    <ul class="nav 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" href="#">About</a>
      </li>
    </ul>
  </div>
</nav>

@pkozlowski-opensource
Copy link
Member

Yep, agree with @jnizet - I think that we are covered here so going to close this one. @ravipunjwani feel free to come back with more info if you believe that we are still missing sth.

@ravipunjwani
Copy link
Author

Hi @jnizet and @pkozlowski-opensource ,

I'm coming back on this issue after many days as I got busy with building rest of my app. Kindly have a look at my explanation below for this issue.

I agree that the ng-collapse is already a feature in ng-bootstrap library but, it works only on a variable e.g. isNavbarCollapsed. That means the variable can be initialized to a value true or false, but this behaviour remains same with all screen sizes.

I would think of a "responsive navbar" that works same as in current example that you provided, additionally with a little logic as follows:

  • in small screen sizes, it should open collapsed. It would look weird when you open an app on mobile and the first think you see is the "expanded navigation".
  • in large screen, it should not be collapsed by default.

Please refer to the sample plunker to describe the problem with code and a little explanation.
http://plnkr.co/edit/0T9TK36RHzZGW9dIBvJf?p=preview

The bootstrap implementation works well as I described. Please follow the second example in bootstrap responsive navbar.

The key here is the usage of class "navbar-toggleable-xs".

@ravipunjwani
Copy link
Author

Hi @pkozlowski-opensource, please update the task status to Open, so that anyone can look into this issue and suggest the feature change.

@pkozlowski-opensource
Copy link
Member

@ravipunjwani I had another look at this one and IMO we do behave exactly as BS.

Here is a simple plunker I've created: http://plnkr.co/edit/4GJl2bBLsjHGhEjn48hx?p=preview
As far as I can tell it matches 1:1 behaviour of the demo http://v4-alpha.getbootstrap.com/components/navbar/#collapsible-content

The way the display of the navbar is driven is be CSS only and there is no JS logic in collapse nor in any other place (at least as far as I can tell).

If you are after setting the initial state of the collapse you could do it based on the viewport size or use sth fancy like media queries from JS: https://www.sitepoint.com/javascript-media-queries/. In any case I don't think there should be any logic for this on the ng-bootstrap side.

Given all the above I'm going to close this issue for now. Open to re-considering if you can demonstrate that we are behaving differently as compared to Bootstrap 4.

@rolandoldengarm
Copy link

While I agree that with collapse you can implement the navbar, it would be even better to implement a navbar component that USES Collapse..
That way there's a one-on-one mapping from bs4 components to ng-bootstrap components.

This is the same approach we've taken for ng-officeuifabric, and you end up with some very simple components, but for the end user it's very easy and there's no discussion about which directive/component to use.
My main concern with your approach here is that the user needs to copy/paste HTML and worry about other stuff like responsiveness, while I think that should be handled by ng-bootstrap. @pkozlowski-opensource

@pkozlowski-opensource
Copy link
Member

While I agree that with collapse you can implement the navbar, it would be even better to implement a navbar component that USES Collapse..

The problem with a dedicated navbar component is that you would have to take arbitrary decisions that might limit what users can do (less flexibility). Indeed a component would have to have a template and any markup you put in this template harder to customize by users.

Having said the above I'm not opposed to the idea of a navbar component, I'm just trying to determine if the gain (less code to write etc.) vs. flexibility makes it "worth". Basically if the new abstraction "pays for itself" (any new abstraction has cost on a new API, documentation, things to learn etc.)

@rolandoldengarm if you (or anyone else interested in this feature) could put together a design doc / API proposal we could iterate on it and see if its is worth new API.

@Supratentorial
Copy link

@pkozlowski-opensource Plunker is not working. Locally I get the same result as the Plunker.

@datumgeek
Copy link

i had the above example working, but then upgraded to bootstrap@4.0.0-alpha.6 (from bootstrap@4.0.0-alpha5) and it stopped working.

i noticed that there is a navbar rewrite

i changed my menu like this (and it works now) 😄

<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
  <button class="navbar-toggler navbar-toggler-right" type="button" (click)="isNavbarCollapsed = !isNavbarCollapsed"
          aria-controls="exCollapsingNavbar2" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <a class="navbar-brand" href="#">North America - Conventional</a>
  <div [ngbCollapse]="isNavbarCollapsed" class="collapse navbar-collapse" id="exCollapsingNavbar2">
    <div class="navbar-nav mr-auto">
      <a class="nav-item nav-link" routerLink="/transfers" routerLinkActive="active">Transfers</a>
      <a class="nav-item nav-link" routerLink="/jobs" routerLinkActive="active">Jobs</a>
      <a class="nav-item nav-link" routerLink="/jobs/7" routerLinkActive="active">Job 7</a>
    </div>
  </div>
</nav>

@xmlking
Copy link

xmlking commented Feb 11, 2017

we need auto collapse for ngbCollapse when any link under it clicked:
jquery e.g:

    $('.navbar-collapse ul li a').click(function() {
        /* always close responsive nav after click */
        $('.navbar-toggle:visible').click();
    });

@JohnGalt1717
Copy link

Even with @datumgeek 's fixes this still doesn't work properly because it doesn't know about reactive design and automatically set it correctly as those change.

There needs to be an out of the box navbar that works EXACTLY like the bootstrap example that understands reactive design and works accordingly.

That means:

  1. When it MD or Large the full menu is visible with no button.
  2. When xs or sm the menu is automatically hidden and the button shows up and they can tap on the menu to show it.
  3. If you drag your window size it should automatically react to the size change and when large enough the button should go away and the menu should automatically display and when small enough going back the other way the menu should hide and the button should show.

What it doesn't do right now is know the different sizing and change the value based on reactive design.

I.e. you need a proper navbar control in here because this hack you have right now doesn't actually address the issue and you're requiring major code just to make work what works right out of the box with bootstrap 4 which defeats the purpose of this project.

@clarkj
Copy link

clarkj commented Apr 21, 2017

Has anyone had any success adding a dropdown-link to a navbar? @datumgeek 's solution works for me, but using ngbCollapse with a dropdown inside the navbar results in the dropdown getting put inside the navbar element, not on the body.

This is what I tried:

<nav class="navbar navbar-toggleable-xl navbar-light bg-faded">
        <a class="navbar-brand" routerLink="/">Ember</a>
	 <div class="collapse navbar-collapse">
		<div class="navbar-nav">
			<a class="nav-item nav-link" routerLink="/table" routerLinkActive="active">AR Table</a>
			<a class="nav-item nav-link" routerLink="/analytics" routerLinkActive="active">Dashboard</a>
			<a class="nav-item nav-link disabled"> Workbench</a>
		</div>
		<ul class="nav navbar-nav">
			<li class="nav-item dropdown dropdown-append-to-body">
				<a class="nav-link dropdown-toggle" (click)="navbar.dropdown=!navbar.dropdown" routerLink="/table" id="navbarDropdownMenuLink" [attr.aria-expanded]="dropdown" aria-controlls="collapseExample">Dropdown link</a>
			        <div id = "collapseExample" [ngbCollapse]="!navbar.dropdown" class="dropdown-menu">
					<a class="dropdown-item" href="#">Action</a>
					<a class="dropdown-item" href="#">Another action</a>
					<a class="dropdown-item" href="#">Something else here</a>
				</div>
			</li>
		</ul>
	</div>
	<div class="ml-auto">
		<div class="navbar-nav">
			<a class="nav-item user">test</a>
		</div>
	</div>
</nav>

@wuttke
Copy link

wuttke commented Jun 19, 2017

Works for me (except for initial state which is not collapsed but should be).

Here is how I did the dropDown:

      <li class="nav-item dropdown">
        <div ngbDropdown>
          <a ngbDropdownToggle class="nav-link dropdown-toggle" id="dropdown_mod">TITLE</a>
          <div class="dropdown-menu" aria-labelledby="dropdown_mod">
            <a class="dropdown-item" href="#" *ngFor="let area of areas">{{area}}</a>
          </div>
        </div>
      </li>

@dougamos
Copy link

I was able to replicate bootstraps navbar example with the collapse directive except for animation. The collapse plugin doesn't seem to do the slide in/out animation.

@collindutter
Copy link

Are there plans to implement the slide in/out animation?

@AnthonyCrowcroft
Copy link

I'm finding that neither of these code snippets are working with the current versions of bootstrap and ng-bootstrap. Is there still no plans to implement this and if there isn't is there any chance that there could be a plunker kept up to date.

@mcescalante
Copy link

mcescalante commented Aug 14, 2017

I find the same thing as @AnthonyCrowcroft - the snippets used to work but with the 4.0.0-beta updates, it seems to have changed some syntax and stuff. Yes, I can figure it out myself. I don't want a dedicated page in the docs for this since I agree that [ngbCollapse] can handle it, but it would be really helpful to have a plunkr or even just updated gist with the latest working navbar collapse code. If I end up with some working code this afternoon I will update this comment with a gist of my own.

@pkozlowski-opensource
Copy link
Member

@mcescalante you can always check our demo page code where we've got responsive navbar:

<header class="navbar navbar-light navbar-fixed-top navbar-expand-lg">
<a class="navbar-brand" [routerLink]="['/']" (click)="navbarCollapsed = true">ng-bootstrap</a>
<button class="navbar-toggler navbar-toggler-right" type="button" (click)="navbarCollapsed = !navbarCollapsed"
[attr.aria-expanded]="!navbarCollapsed" aria-controls="navbarContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse" [ngbCollapse]="navbarCollapsed" id="navbarContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item" [routerLinkActive]="['active']">
<a class="nav-link" [routerLink]="['/getting-started']" (click)="navbarCollapsed = true">Getting Started</a>
</li>
<li class="nav-item" [routerLinkActive]="['active']">
<a class="nav-link" [routerLink]="['/components']" (click)="navbarCollapsed = true">Components</a>
</li>
<li class="nav-item d-lg-none" *ngFor="let component of components" [routerLinkActive]="['active']">
<a class="nav-link" [routerLink]="['/components', component.toLowerCase()]" (click)="navbarCollapsed = true">{{ component }}</a>
</li>
</ul>
<span class="github-buttons d-none d-lg-inline">
<a class="github-button"
href="https://github.com/ng-bootstrap/ng-bootstrap"
target="_blank"
data-style="mega"
data-count-href="/ng-bootstrap/ng-bootstrap/stargazers"
data-count-api="/repos/ng-bootstrap/ng-bootstrap#stargazers_count"
data-count-aria-label="# stargazers on GitHub"
aria-label="Star ng-bootstrap/ng-bootstrap on GitHub">Star</a>
<a href="https://twitter.com/intent/tweet?button_hashtag=ngbootstrap"
class="twitter-hashtag-button"
data-size="large"
data-text="I&#39;m checking out ng-bootstrap, THE Angular UI framework for Bootstrap CSS"
data-url="https://ng-bootstrap.github.io"
data-show-count="true">Tweet #ngbootstrap</a>
</span>
</div>
</header>

@mcescalante
Copy link

Ah excellent! This is perfect @pkozlowski-opensource thank you very much!

@kerryhatcher
Copy link

@pkozlowski-opensource That snippet was exactly what I was looking for. Methinks there needs to be something in the docs about this. Wasn't obvious to me as a newbie ng-bootstrap user (but long time bootstrap user)

@chedched
Copy link

Does anyone have a plunkr for the latest version? I don't manage to make it run.

@kamok
Copy link

kamok commented Oct 13, 2017

I wanted to try Bootstrap 4 in hopes of getting access to some of their new goodies, but seeing how it's so difficult to get something as simple as a navbar to work is quite disheartening. The code on the documentation for Bootstrap 4 simply doesn't work with the latest version of Angular. The code from @pkozlowski-opensource works, but it seems like a lot of hoops and hurdles just to get one of the most basic components to work. (The hurdle being having to look up issues in ng-bootstrap when it should just work)

@brijmcq
Copy link

brijmcq commented Oct 19, 2017

@dougamos @collindutter You can add the angular/animations to have that slide-in/out effect.

<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
	<div class="container">
		<a href="#" class="navbar-brand">ngbs-1</a>
     <button class="navbar-toggler" (click)="toggleNavbar()"  type="button" aria-controls="theNavbar" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
		<div [ngbCollapse]="isNavbarCollapsed" id="theNavbar"
     [@collapse]="isNavbarCollapsedAnim"
     class="navbar-collapse collapse navbar-toggleable">
			<ul class="navbar-nav mr-auto ml-auto"> 
				<li class="nav-item">
					<a class="nav-link" href="#"> Home</a>
				</li>
				<li class="nav-item">
					<a class="nav-link" href="#"> About</a>
				</li>
				<li class="nav-item">
					<a class="nav-link" href="#"> Contact</a>
				</li>
			</ul>
		</div>
	</div>
</nav>

And in your component

import {  trigger,state,style, animate, transition } from '@angular/animations'; 
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
   animations: [
  trigger('collapse', [
    state('open', style({
      opacity: '1'
    })),
    state('closed',   style({
      opacity: '0',
      display: 'none',   
    })),
    transition('closed => open', animate('400ms ease-in')),
    transition('open => closed', animate('100ms ease-out'))
  ])
]
})
export class AppComponent {
  isNavbarCollapsed = true;
  _isNavbarCollapsedAnim = 'closed';
  ngOnInit() {
    this.onResize(window);
  }
  @HostListener('window:resize', ['$event.target']) 
onResize(event) { 
  if(event.innerWidth > 990){
    //need to set this to 'open' for large screens to show up because of opacity in 'closed' animation.
    this._isNavbarCollapsedAnim = 'open';
      this.isNavbarCollapsed = true;
  }else{
    // comment this line if you don't want to collapse the navbar when window is resized.
   // this._isNavbarCollapsedAnim = 'closed';
  }
}
  toggleNavbar(): void {
    if(this.isNavbarCollapsed){
        this._isNavbarCollapsedAnim = 'open';
      this.isNavbarCollapsed = false;
    } else {
    this._isNavbarCollapsedAnim = 'closed';
      this.isNavbarCollapsed = true;
    }
  }
  get isNavbarCollapsedAnim() : string {
    return this._isNavbarCollapsedAnim;
  }
}

Here's a stackblitz demo https://stackblitz.com/edit/ng-bri-bs1-armbhz?file=app%2Fapp.component.html

vyruz1986 added a commit to vyruz1986/FlyballETS-WebUI that referenced this issue Oct 20, 2017
- Upgraded to bootstrap v4 beta2
- Removed bootstrap JS
- Added ng-bootstrap
- Fixed menu (now works with mobile devices) as per example of ng-bootstrap/ng-bootstrap#738 (comment)
@yanshuf0
Copy link

yanshuf0 commented Feb 25, 2018

Lol this is actually bs that the accepted answer was "here's this directive which doesn't do 90% of what the bootstrap component does, but deal with it." Paste the code from the first response into your ide and compare it with the BS4 component. Just terrible. I also like how the last response is 50+ lines of code to do what the BS4 component does in one. Defeating the purpose of using bootstrap, or angular for that matter. Why not just use es5 and some html and css, technically you COULD achieve everything bootstrap offers. Sad!

@Louspirit
Copy link

Louspirit commented Jun 28, 2018

I found this interesting article that explains the purpose of ng-bootstrap and why we shouldn't give it up (even if we have to write more code) : https://stevenschwenke.de/AngularAndBootstrapUseNg-bootstrap.

Basically Angular works with components where jquery interacts with the DOM itself. While Jquery can break the app, ng-bootstrap is written the angular way and you keep the control over your components.

@matthiasbraun
Copy link

The default ngbCollapse example works also for small initial screen sizes, if you set the initial value of isCollapsed to true (even if this is not really "true" for larger screen sizes, but it works)

@samantha-holder
Copy link

The ngbCollapse is only tied to the onclick button action though. If you increase the window size to hide the 'hamburger' button the 'show' property is still active on the div. Then next time you reduce window size you'll see an already active dropdown. The collapsed menu should be hidden by default every time the 'hamburger' makes an appearance. It should not persisted.

@benjavalero
Copy link

For me, just adding (click)="navbarCollapsed = true" to the a links has made the trick:

@mcescalante you can always check our demo page code where we've got responsive navbar:

<header class="navbar navbar-light navbar-fixed-top navbar-expand-lg">
<a class="navbar-brand" [routerLink]="['/']" (click)="navbarCollapsed = true">ng-bootstrap</a>
<button class="navbar-toggler navbar-toggler-right" type="button" (click)="navbarCollapsed = !navbarCollapsed"
[attr.aria-expanded]="!navbarCollapsed" aria-controls="navbarContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse" [ngbCollapse]="navbarCollapsed" id="navbarContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item" [routerLinkActive]="['active']">
<a class="nav-link" [routerLink]="['/getting-started']" (click)="navbarCollapsed = true">Getting Started</a>
</li>
<li class="nav-item" [routerLinkActive]="['active']">
<a class="nav-link" [routerLink]="['/components']" (click)="navbarCollapsed = true">Components</a>
</li>
<li class="nav-item d-lg-none" *ngFor="let component of components" [routerLinkActive]="['active']">
<a class="nav-link" [routerLink]="['/components', component.toLowerCase()]" (click)="navbarCollapsed = true">{{ component }}</a>
</li>
</ul>
<span class="github-buttons d-none d-lg-inline">
<a class="github-button"
href="https://github.com/ng-bootstrap/ng-bootstrap"
target="_blank"
data-style="mega"
data-count-href="/ng-bootstrap/ng-bootstrap/stargazers"
data-count-api="/repos/ng-bootstrap/ng-bootstrap#stargazers_count"
data-count-aria-label="# stargazers on GitHub"
aria-label="Star ng-bootstrap/ng-bootstrap on GitHub">Star</a>
<a href="https://twitter.com/intent/tweet?button_hashtag=ngbootstrap"
class="twitter-hashtag-button"
data-size="large"
data-text="I&#39;m checking out ng-bootstrap, THE Angular UI framework for Bootstrap CSS"
data-url="https://ng-bootstrap.github.io"
data-show-count="true">Tweet #ngbootstrap</a>
</span>
</div>
</header>

@moolsbytheway
Copy link

moolsbytheway commented Mar 14, 2021

@AtozEvo
Copy link

AtozEvo commented Nov 11, 2021

I would just like to raise an opinion as a new @ng-bootstrap/ng-bootstrap / boostrap use (with angular). I think there should at least be a Navbar 'page' on the docs to explain that Navbar is basically implementing ngbCollaspe.

After a bunch of searching (and googling, and thinking "There's no way ng-boostrap wouldn't have a navbar component since bootstrap has one") I stumbled on the doc/example in nbgCollaspe's document. My first thought was, "Why is it here?".

Maybe move the Responsive Navbar section in the ngbCollaspe page to its own page or have a link 'components/collapse/examples#navbar' on a navbar page. I mean, the fragment is already called 'navbar'. I'm just thinking it'll be easier to find for newbies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests