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

Commit

Permalink
feat(sidenav): add promise-based lookup .then(callbackFn) for deferre…
Browse files Browse the repository at this point in the history
…d instances

Closes #1311.
  • Loading branch information
ThomasBurleson committed Apr 6, 2015
1 parent f3cd5b9 commit 076a97d
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 13 deletions.
76 changes: 63 additions & 13 deletions src/components/sidenav/sidenav.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,44 +29,71 @@ angular.module('material.components.sidenav', [
*
* @usage
* <hljs lang="js">
* // Toggle the given sidenav
* $mdSidenav(componentId).toggle();
* // Async lookup for sidenav instance; will resolve when the instance is available
* $mdSidenav(componentId).then(function(instance) {
* $log.debug( componentId + "is now ready" );
* });
* </hljs>
* <hljs lang="js">
* // Async toggle the given sidenav;
* // when instance is known ready and lazy lookup is not needed.
* $mdSidenav(componentId)
* .toggle()
* .then(function(){
* $log.debug('toggled');
* });
* </hljs>
* <hljs lang="js">
* // Open the given sidenav
* $mdSidenav(componentId).open();
* // Async open the given sidenav
* $mdSidenav(componentId)
* .open();
* .then(function(){
* $log.debug('opened');
* });
* </hljs>
* <hljs lang="js">
* // Close the given sidenav
* $mdSidenav(componentId).close();
* // Async close the given sidenav
* $mdSidenav(componentId)
* .close();
* .then(function(){
* $log.debug('closed');
* });
* </hljs>
* <hljs lang="js">
* // Exposes whether given sidenav is set to be open
* // Sync check to see if the specified sidenav is set to be open
* $mdSidenav(componentId).isOpen();
* </hljs>
* <hljs lang="js">
* // Exposes whether given sidenav is locked open
* // If this is true, the sidenav will be open regardless of isOpen()
* // Sync check to whether given sidenav is locked open
* // If this is true, the sidenav will be open regardless of close()
* $mdSidenav(componentId).isLockedOpen();
* </hljs>
*/
function SidenavService($mdComponentRegistry, $q) {
return function(handle) {
var errorMsg = "SideNav '" + handle + "' is not available!";

// Lookup the controller instance for the specified sidNav instance
var self;
var errorMsg = "SideNav '" + handle + "' is not available!";
var instance = $mdComponentRegistry.get(handle);

if(!instance) {
$mdComponentRegistry.notFoundError(handle);
}

return {
return self = {
// -----------------
// Sync methods
// -----------------
isOpen: function() {
return instance && instance.isOpen();
},
isLockedOpen: function() {
return instance && instance.isLockedOpen();
},
// -----------------
// Async methods
// -----------------
toggle: function() {
return instance ? instance.toggle() : $q.reject(errorMsg);
},
Expand All @@ -75,8 +102,24 @@ function SidenavService($mdComponentRegistry, $q) {
},
close: function() {
return instance ? instance.close() : $q.reject(errorMsg);
},
then : function( callbackFn ) {
var promise = instance ? $q.when(instance) : waitForInstance();
return promise.then( callbackFn || angular.noop );
}
};

/**
* Deferred lookup of component instance using $component registry
*/
function waitForInstance() {
return $mdComponentRegistry
.when(handle)
.then(function( it ){
instance = it;
return it;
});
}
};
}

Expand Down Expand Up @@ -162,7 +205,10 @@ function SidenavDirective($timeout, $animate, $parse, $log, $mdMedia, $mdConstan
var isLockedOpenParsed = $parse(attr.mdIsLockedOpen);
var isLocked = function() {
return isLockedOpenParsed(scope.$parent, {
$media: function(arg) { $log.warn("$media is deprecated for is-locked-open. Use $mdMedia instead."); return $mdMedia(arg); },
$media: function(arg) {
$log.warn("$media is deprecated for is-locked-open. Use $mdMedia instead.");
return $mdMedia(arg);
},
$mdMedia: $mdMedia
});
};
Expand Down Expand Up @@ -311,13 +357,17 @@ function SidenavController($scope, $element, $attrs, $mdComponentRegistry, $q) {

// Use Default internal method until overridden by directive postLink

self.$toggleOpen = function() { return $q.when($scope.isOpen); };
// Synchronous getters
self.isOpen = function() { return !!$scope.isOpen; };
self.isLockedOpen = function() { return !!$scope.isLockedOpen; };

// Async actions
self.open = function() { return self.$toggleOpen( true ); };
self.close = function() { return self.$toggleOpen( false ); };
self.toggle = function() { return self.$toggleOpen( !$scope.isOpen ); };

self.$toggleOpen = function() { return $q.when($scope.isOpen); };

self.destroy = $mdComponentRegistry.register(self, $attrs.mdComponentId);
}

Expand Down
31 changes: 31 additions & 0 deletions src/components/sidenav/sidenav.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,15 @@ describe('mdSidenav', function() {
});

describe('$mdSidenav Service', function() {
var $rootScope, $timeout;


beforeEach( inject(function(_$rootScope_,_$timeout_) {
$rootScope = _$rootScope_;
$timeout = _$timeout_;
}));


it('should grab instance', inject(function($mdSidenav) {
var el = setup('md-component-id="left"');
var scope = el.isolateScope();
Expand Down Expand Up @@ -253,6 +262,28 @@ describe('mdSidenav', function() {
expect(instance.isOpen()).toBe(false);
expect(instance.isLockedOpen()).toBe(true);
}));

it('should find a deferred instantiation', inject(function($mdSidenav) {
var instance;

// Lookup deferred (not existing) instance
$mdSidenav('left').then( function(inst) { instance = inst; });
expect(instance).toBeUndefined();

// Instantiate `left` sidenav component
var el = setup('md-component-id="left"');

$timeout.flush();
expect(instance).toBeTruthy();
expect(instance.isOpen()).toBeFalsy();

// Lookup instance still available in the component registry
instance = undefined;
instance = $mdSidenav('left');

expect(instance).toBeTruthy();

}));
});

});

0 comments on commit 076a97d

Please sign in to comment.