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

Commit 4cc21fe

Browse files
committed
fix(sidenav): allow for data bindings in md-component-id
Fixes the sidenav not evaluating expressions inside of the `md-component-id` attribute. Fixes #9052.
1 parent 9fa6a97 commit 4cc21fe

File tree

2 files changed

+47
-23
lines changed

2 files changed

+47
-23
lines changed

src/components/sidenav/sidenav.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,7 @@ function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $animate,
249249
},
250250
controller: '$mdSidenavController',
251251
compile: function(element) {
252-
element.addClass('md-closed');
253-
element.attr('tabIndex', '-1');
252+
element.addClass('md-closed').attr('tabIndex', '-1');
254253
return postLink;
255254
}
256255
};
@@ -481,9 +480,8 @@ function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $animate,
481480
* @ngdoc controller
482481
* @name SidenavController
483482
* @module material.components.sidenav
484-
*
485483
*/
486-
function SidenavController($scope, $element, $attrs, $mdComponentRegistry, $q) {
484+
function SidenavController($scope, $attrs, $mdComponentRegistry, $q, $interpolate) {
487485

488486
var self = this;
489487

@@ -505,5 +503,19 @@ function SidenavController($scope, $element, $attrs, $mdComponentRegistry, $q) {
505503
self.toggle = function() { return self.$toggleOpen( !$scope.isOpen ); };
506504
self.$toggleOpen = function(value) { return $q.when($scope.isOpen = value); };
507505

508-
self.destroy = $mdComponentRegistry.register(self, $attrs.mdComponentId);
506+
// Evaluate the component id.
507+
var rawId = $attrs.mdComponentId;
508+
var componentId = rawId && rawId.indexOf($interpolate.startSymbol()) > -1 ?
509+
$interpolate(rawId)($scope.$parent) : rawId;
510+
511+
// Register the component.
512+
self.destroy = $mdComponentRegistry.register(self, componentId);
513+
514+
// Watch and update the component, if the id has changed.
515+
$attrs.$observe('mdComponentId', function(id) {
516+
if (id && id !== self.$$mdHandle) {
517+
self.destroy();
518+
self.destroy = $mdComponentRegistry.register(self, id);
519+
}
520+
});
509521
}

src/components/sidenav/sidenav.spec.js

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
describe('mdSidenav', function() {
22
beforeEach(module('material.components.sidenav'));
33

4-
function setup(attrs) {
4+
function setup(attrs, skipInitialDigest) {
55
var el;
66
inject(function($compile, $rootScope) {
77
var parent = angular.element('<div>');
88
el = angular.element('<md-sidenav ' + (attrs || '') + '>');
99
parent.append(el);
1010
$compile(parent)($rootScope);
11-
$rootScope.$apply();
11+
!skipInitialDigest && $rootScope.$apply();
1212
});
1313
return el;
1414
}
@@ -168,13 +168,13 @@ describe('mdSidenav', function() {
168168

169169
describe('controller', function() {
170170
it('should create controller', function() {
171-
var el = setup('');
171+
var el = setup();
172172
var controller = el.controller('mdSidenav');
173173
expect(controller).not.toBe(undefined);
174174
});
175175

176176
it('should open and close and toggle', inject(function($timeout) {
177-
var el = setup('');
177+
var el = setup();
178178
var scope = el.isolateScope();
179179
var controller = el.controller('mdSidenav');
180180

@@ -213,7 +213,7 @@ describe('mdSidenav', function() {
213213
}));
214214

215215
it('should open(), close(), and toggle() with promises', function() {
216-
var el = setup('');
216+
var el = setup();
217217
var scope = el.isolateScope();
218218
var controller = el.controller('mdSidenav');
219219

@@ -257,7 +257,7 @@ describe('mdSidenav', function() {
257257
});
258258

259259
it('should open() to work multiple times before close()', function() {
260-
var el = setup('');
260+
var el = setup();
261261
var controller = el.controller('mdSidenav');
262262

263263
var openDone = 0, closeDone = 0;
@@ -351,23 +351,35 @@ describe('mdSidenav', function() {
351351
});
352352

353353
describe('$mdSidenav lookups', function() {
354-
var $rootScope, $timeout;
354+
var $rootScope, $timeout, $mdSidenav;
355355

356-
beforeEach(inject(function(_$rootScope_, _$timeout_) {
356+
beforeEach(inject(function(_$rootScope_, _$timeout_, _$mdSidenav_) {
357357
$rootScope = _$rootScope_;
358358
$timeout = _$timeout_;
359+
$mdSidenav = _$mdSidenav_;
359360
}));
360361

361-
it('should find an instantiation using `$mdSidenav(id)`', inject(function($mdSidenav) {
362+
it('should find an instantiation using `$mdSidenav(id)`', function() {
362363
var el = setup('md-component-id="left"');
363364
$timeout.flush();
364365

365366
// Lookup instance still available in the component registry
366367
var instance = $mdSidenav('left');
367368
expect(instance).toBeTruthy();
368-
}));
369+
});
369370

370-
it('should find a deferred instantiation using `$mdSidenav(id, true)`', inject(function($mdSidenav) {
371+
it('should support data bindings', function() {
372+
// It should work on init.
373+
$rootScope.leftComponentId = 'left';
374+
setup('md-component-id="{{ leftComponentId }}"', true);
375+
expect($mdSidenav($rootScope.leftComponentId, false)).toBeTruthy();
376+
377+
// It should also work if the data binding has changed.
378+
$rootScope.$apply('leftComponentId = "otherLeft"');
379+
expect($mdSidenav($rootScope.leftComponentId, false)).toBeTruthy();
380+
});
381+
382+
it('should find a deferred instantiation using `$mdSidenav(id, true)`', function() {
371383
var instance;
372384

373385
// Lookup deferred (not existing) instance
@@ -386,9 +398,9 @@ describe('mdSidenav', function() {
386398
// Lookup instance still available in the component registry
387399
instance = $mdSidenav('left', true);
388400
expect(instance).toBeTruthy();
389-
}));
401+
});
390402

391-
it('should find a deferred instantiation using `$mdSidenav().waitFor(id)` ', inject(function($mdSidenav) {
403+
it('should find a deferred instantiation using `$mdSidenav().waitFor(id)` ', function() {
392404
var instance;
393405

394406
// Lookup deferred (not existing) instance
@@ -409,9 +421,9 @@ describe('mdSidenav', function() {
409421
instance = $mdSidenav('left');
410422

411423
expect(instance).toBeTruthy();
412-
}));
424+
});
413425

414-
it('should not find a lazy instantiation without waiting `$mdSidenav(id)`', inject(function($mdSidenav) {
426+
it('should not find a lazy instantiation without waiting `$mdSidenav(id)`', function() {
415427
var instance = $mdSidenav('left');
416428
expect(instance.isOpen).toBeDefined(); // returns legacy API with noops
417429

@@ -425,9 +437,9 @@ describe('mdSidenav', function() {
425437
instance = $mdSidenav('left'); // returns instance
426438
expect(instance).toBeDefined();
427439
expect(instance.isOpen()).toBeFalsy();
428-
}));
440+
});
429441

430-
it('should not find a lazy instantiation without waiting `$mdSidenav().find(id)`', inject(function($mdSidenav) {
442+
it('should not find a lazy instantiation without waiting `$mdSidenav().find(id)`', function() {
431443
var instance = $mdSidenav().find('left');
432444
expect(instance).toBeUndefined();
433445

@@ -438,7 +450,7 @@ describe('mdSidenav', function() {
438450
instance = $mdSidenav().find('left');
439451
expect(instance).toBeDefined();
440452
expect(instance.isOpen()).toBeFalsy();
441-
}));
453+
});
442454

443455
describe('onClose', function () {
444456
it('should call callback on escape', inject(function($mdSidenav, $rootScope, $material, $mdConstant, $timeout) {

0 commit comments

Comments
 (0)