Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

md-sidenav: add possibility to programmatically close sidebar even with md-is-locked-open attribute #3027

Closed
smashercosmo opened this issue May 29, 2015 · 19 comments
Assignees
Milestone

Comments

@smashercosmo
Copy link

I think, that behaviour should be the following:

  1. Sidebar opens when md-is-locked-open expression becomes thruthy
  2. We can close sidebar programmatically by envoking close or toggle method
  3. If we did so sidebar remains closed whatever the value of md-is-locked-open expression is
  4. If we then open sidebar programmatically normal md-is-locked-open behaviour returns.
@dwanderton
Copy link

+1

@freitag-solutions
Copy link

+1

The requested behavior (ability to close an md-is-locked-open md-sidenav) seems conform with the material design spec.

The current implementation only allows using the md-sidenav widget as permanent navigation drawer or temporary navigation drawer, but the specs explicitly mention persisent navigation drawers.

http://www.google.com/design/spec/patterns/navigation-drawer.html#navigation-drawer-behavior

Persistent navigation drawers can toggle open or closed. The drawer sits on the same surface elevation as the content. It is closed by default and opens by selecting the menu icon, and stays open until closed by the user. The state of the drawer is remembered from action to action and session to session.

Sitting outside of the page grid, when opened the drawer forces other content to change size and adapt to the smaller viewport.

Persistent navigation drawers are acceptable for all sizes larger than mobile.

Providing the possibility to toggle an md-is-locked-open``md-sidenav would allow using it as persisent navigation drawer.

@imjoeybrennan
Copy link

+1

@ricardobfa
Copy link

+1

@mzbyszynski
Copy link
Contributor

Couldn't you just use the md-is-locked-open expression to accomplish this? You can string together multiple conditions in that expression to account for different states. It seems like a good option for maintaining persistent state between sessions as @freitag-solutions's quote from the design spec mentions, since you could initialize the state from persistent storage when the app starts up.

Here's a quick-and-dirty example that relies on parent scopes, but there are a number of ways you could do it:

http://codepen.io/mzbyszynski/pen/aOEQJX

Click the "Unlock Sidenav Left" button to unlock the sidenav.

Or am I misunderstanding what you are asking for?

@smashercosmo
Copy link
Author

@mzbyszynski yep, that's definitely a simple solution. Ashamed of not being able to come up to such obvious answer to the problem (( thanks. Closing.

@freitag-solutions
Copy link

While I see how @mzbyszynski's method somewhat fixes the problem (I'm already using a similar approach but totally forgot about this issue sorry!), I rather see it as hackfix than final solution. Nonetheless, thank you for the snippet and for taking a look at the problem @mzbyszynski!

The problem I see is that it still needs two different methods for toggling the sidenav depending on whether it is persistent or not. If it is persistent one needs to toggle md-is-locked-open, if it is non-persistent one needs to toggle md-is-open (in @mzbyszynski's codepen this corresponds to the methods 'unlock/lock sidebar' vs. 'toggle sidebar').

In my humble opinion it would be great to have a common way of interacting with the md-sidenav directive, regardless of it being used as persistent or non-persistent drawer.

My personal approach for a hybrid sidenav (persistent on large devices, non-persistent on small ones) as in @mzbyszynski's snippet is the following (see http://codepen.io/anon/pen/XbVyww for the actual implementation) :

md-is-open = $scope.isOpen
md-is-locked-open = $scope.IsOpen && $mdMedia('gt-md')

In my opinion, this is a very intuitive way of configuring such a hybrid sidenav and also somewhat works as expected. Unfortunately when toggling both properties to false (md-is-open, md-is-locked-open) a backdrop supporting the closing animation is shown, resulting in a somehow buggy experience and the need for another hack: e.g. hiding the backdrop via css when the sidenav is supposed to be persistent.

So, I still see the need for some fixing.
Probably it still would be great to have the toggle method work on locked sidenavs.
Maybe the method mentioned above should work without irritating backdrop.
In the end, I think the different modes of the sidenav (persisent/non-persistent) should at least have a common interface and should not need to be configured via independent properties (as it is currently the case where md-is-open controls non-persistent sidenavs and md-is-locked-open controls persistent ones but both cannot be used together).

What do you think?

@pdore-netfore
Copy link
Contributor

@freitag-solutions What is your CSS 'hack' to remove the backdrop?

@andrea-vega
Copy link

@mzbyszynski it seems that the codepen example does not work as nicely with the latest master branch. I get an md-backdrop flash on close, and no animation. I'd love to see something like $mdSidenav('left').toggleLocked();

If it helps , my use case is a data table that takes up as much of the real estate as possible. Then optionally, a filter sidebar can be opened to drill down (like Amazon's refine by).

@mzbyszynski
Copy link
Contributor

@andrea-vega I think the issues you are seeing might be related to #4152. When I use angular material 0.10.1 with angular 1.3 the animations seem to work ok, but when I change to 1.4.4 then I don't see the animation anymore. I didn't notice the backdrop flashing but it might be.

Angular 1.3.15 + Angular Material 0.10.0:
http://codepen.io/mzbyszynski/pen/aOEQJX

Angular 1.3.15 + Angular Material 0.10.1:
http://codepen.io/mzbyszynski/pen/EjqXJW

Angular 1.4.4 + Angular material 0.10.1:
http://codepen.io/mzbyszynski/pen/ZGgyNO

@elawad
Copy link

elawad commented Sep 7, 2015

@pdore-netfore Here's the css I used to remove the backdrop (except on mobile):

@media (min-width: 600px) {
  md-backdrop.md-sidenav-backdrop {
    display: none;
  }
}

Preview: http://gfycat.com/BleakBriefHarrierhawk

@bonatoc
Copy link

bonatoc commented Sep 20, 2015

@mzbyszynski — I read somewhere around here that it is fixed with 1.4.5.

and also, that $mdSidenav is about to be refactored soon,
because right now it's just a fancy proof of concept.

@omeid
Copy link

omeid commented Nov 29, 2015

@sm+1

The proposed solution is a hack and is inconsistent with $mdSidenav service.

@MikaelLandau
Copy link

I achieved this the following way:

<md-sidenav ng-show="ctrl.showSidebar"  layout-column md-component-id="left" md-is-locked-open="$mdMedia('gt-sm')">
  <md-content layout-fill role="navigation">
  </md-content>
</md-sidenav>

And then in JS:

 self.showSidebar = true;
 self.toggleSideBar = function(){
   self.showSidebar = !self.showSidebar;
 };

@PsyGik
Copy link

PsyGik commented Jan 31, 2016

@MikaelLandau But what about the sliding animation?

@bonatoc
Copy link

bonatoc commented Jan 31, 2016

@PsyGik - I think all happens through CSS classes dynamically injected/removed according to the SIdebar's state. But I could be wrong.

@ghost
Copy link

ghost commented Feb 24, 2016

Edit: Nevermind my comment, it is actually working..

@royston-c
Copy link

In order to remove the flash of the backdrop. I used a variable for each attribute.

<md-sidenav md-component-id="left-sidenav" md-is-open="viewModel.leftSidenavOpen" md-is-locked-open="$mdMedia('gt-md') && viewModel.leftSidenavLockedOpen" >
  <md-content layout-fill role="navigation">
  </md-content>
</md-sidenav>
self.toggleLeftSidenav = function(){
  if (self.$mdMedia('gt-md')) {
    self.leftSidenavLockedOpen = !self.leftSidenavLockedOpen;
  } else {
    self.leftSidenavOpen = !self.leftSidenavOpen;
  }
};

This also allows you to control if the sidenav is open once the screen size is changed. I personally expect the sidenav to disappear and not to become an overlay if the screen size hits the lower size.

self.toggleLeftSidenav = function(){
  if (self.$mdMedia('gt-md')) {
    self.leftSidenavOpen = false;
    self.leftSidenavLockedOpen = !self.leftSidenavLockedOpen;
  } else {
    self.leftSidenavOpen = !self.leftSidenavOpen;
  }
};

Tested with v1.0.5.

@yellownoggin
Copy link

yellownoggin commented Jun 20, 2016

thx @roy46

work well...

I just had to initialize the self.leftSidenavLockedOpen on controller initialization, in addition to your code

self.leftSidenavLockedOpen = $mdMedia('gt-md');

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

No branches or pull requests