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

fix(sidenav): allow to hide side nav depending on the media query #11581

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 38 additions & 10 deletions src/components/sidenav/sidenav.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ function SidenavService($mdComponentRegistry, $mdUtil, $q, $log) {

return angular.extend({
isLockedOpen: falseFn,
isLockedClosed: falseFn,
isOpen: falseFn,
toggle: rejectFn,
open: rejectFn,
Expand Down Expand Up @@ -244,16 +245,19 @@ function SidenavFocusDirective() {
* @param {expression=} md-is-locked-open When this expression evaluates to true,
* the sidenav 'locks open': it falls into the content's flow instead
* of appearing over it. This overrides the `md-is-open` attribute.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the MD Spec's Surface Behaviors when this value is true, it maps to Permanent. The default when this is false is Temporary. If you want to implement the Persistant behavior, then you need to allow the value of md-is-locked-open to be toggled like in this CodePen example.

We should link to this part of the spec in the main SideNav docs (above) and mention these behavior names. We also need to have demos of each type of behavior (could be as part of 1 or 2 demos).

* @param {expression=} md-is-locked-closed When this expression evaluates to true,
* the sidenav 'locks closed': hides sidenav.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still trying to get a handle on what behavior this API really has and how to name it.

Based on the naming, md-is-locked-closed="true" should make it so that you can't open the sidenav at all, even via toggle(). But in this CodePen you can see that is not the case. This doesn't mean that your behavior is incorrect, it just means that we have the wrong naming of this API here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Splaktar what if I change it to md-is-hidden, is-hidden-when or md-hide-when?
Basically by specifying the condition you determine when the sidenav has to become closed after it was opened.

* @param {string=} md-disable-scroll-target Selector, pointing to an element, whose scrolling will
* be disabled when the sidenav is opened. By default this is the sidenav's direct parent.
*
* The $mdMedia() service is exposed to the is-locked-open attribute, which
* The $mdMedia() service is exposed to the is-locked-open and is-locked-closed attributes, which
* can be given a media query or one of the `sm`, `gt-sm`, `md`, `gt-md`, `lg` or `gt-lg` presets.
* Examples:
*
* - `<md-sidenav md-is-locked-open="shouldLockOpen"></md-sidenav>`
* - `<md-sidenav md-is-locked-open="$mdMedia('min-width: 1000px')"></md-sidenav>`
* - `<md-sidenav md-is-locked-open="$mdMedia('sm')"></md-sidenav>` (locks open on small screens)
* - `<md-sidenav md-is-locked-closed="$mdMedia('sm')"></md-sidenav>` (locks closed on small screens)
*/
function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $mdInteraction, $animate,
$compile, $parse, $log, $q, $document, $window, $$rAF) {
Expand Down Expand Up @@ -282,8 +286,9 @@ function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $mdInterac
var previousContainerStyles;
var promise = $q.when(true);
var isLockedOpenParsed = $parse(attr.mdIsLockedOpen);
var isLockedClosedParsed = $parse(attr.mdIsLockedClosed);
var ngWindow = angular.element($window);
var isLocked = function() {
var isLockedOpen = function() {
return isLockedOpenParsed(scope.$parent, {
$media: function(arg) {
$log.warn("$media is deprecated for is-locked-open. Use $mdMedia instead.");
Expand All @@ -292,6 +297,15 @@ function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $mdInterac
$mdMedia: $mdMedia
});
};
var isLockedClosed = function() {
return isLockedClosedParsed(scope.$parent, {
$media: function(arg) {
$log.warn("$media is deprecated for is-locked-closed. Use $mdMedia instead.");
return $mdMedia(arg);
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that we need to add this old deprecated API warning for the new isLockedClosed API.

$mdMedia: $mdMedia
});
};

if (attr.mdDisableScrollTarget) {
disableScrollTarget = $document[0].querySelector(attr.mdDisableScrollTarget);
Expand Down Expand Up @@ -336,7 +350,8 @@ function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $mdInterac
backdrop && backdrop.remove();
});

scope.$watch(isLocked, updateIsLocked);
scope.$watch(isLockedOpen, updateIsLockedOpen);
scope.$watch(isLockedClosed, updateIsLockedClosed);
scope.$watch('isOpen', updateIsOpen);


Expand All @@ -345,18 +360,30 @@ function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $mdInterac

/**
* Toggle the DOM classes to indicate `locked`
* @param isLocked
* @param isLockedOpen
* @param oldValue
*/
function updateIsLocked(isLocked, oldValue) {
scope.isLockedOpen = isLocked;
if (isLocked === oldValue) {
element.toggleClass('md-locked-open', !!isLocked);
function updateIsLockedOpen(isLockedOpen, oldValue) {
scope.isLockedOpen = isLockedOpen;
if (isLockedOpen === oldValue) {
element.toggleClass('md-locked-open', !!isLockedOpen);
} else {
$animate[isLocked ? 'addClass' : 'removeClass'](element, 'md-locked-open');
$animate[isLockedOpen ? 'addClass' : 'removeClass'](element, 'md-locked-open');
}
if (backdrop) {
backdrop.toggleClass('md-locked-open', !!isLocked);
backdrop.toggleClass('md-locked-open', !!isLockedOpen);
}
}

/**
* Toggle the DOM classes to indicate `locked`
* @param isLockedClosed
* @param oldValue
*/
function updateIsLockedClosed(isLockedClosed, oldValue) {
scope.isLockedClosed = isLockedClosed;
if (true === !!isLockedClosed) {
sidenavCtrl.close();
}
}

Expand Down Expand Up @@ -535,6 +562,7 @@ function SidenavController($scope, $attrs, $mdComponentRegistry, $q, $interpolat
// Synchronous getters
self.isOpen = function() { return !!$scope.isOpen; };
self.isLockedOpen = function() { return !!$scope.isLockedOpen; };
self.isLockedClosed = function() { return !!$scope.isLockedClosed; };

// Synchronous setters
self.onClose = function (callback) {
Expand Down