Skip to content

Commit 2a2e5de

Browse files
committed
refactor(datepicker): implement one time bindings
Reducing the number of watches created for the datepicker by implementing one time binding on the datepicker templates. Removing aria-disabled attribute as the ngAria module will add that to the button with ng-disabled. Closes angular-ui#3443
1 parent 21b2002 commit 2a2e5de

File tree

4 files changed

+45
-49
lines changed

4 files changed

+45
-49
lines changed

Diff for: src/datepicker/test/datepicker.spec.js

+30-34
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ describe('datepicker directive', function () {
5959
return element.find('thead').find('tr').eq(1);
6060
}
6161

62-
function getLabels() {
62+
function getLabels(dayMode) {
6363
var els = getLabelsRow().find('th'),
6464
labels = [];
65-
for (var i = 1, n = els.length; i < n; i++) {
65+
for (var i = dayMode ? 1 : 0, n = els.length; i < n; i++) {
6666
labels.push( els.eq(i).text() );
6767
}
6868
return labels;
@@ -77,7 +77,7 @@ describe('datepicker directive', function () {
7777
return weeks;
7878
}
7979

80-
function getOptions( dayMode ) {
80+
function getOptions(dayMode) {
8181
var tr = element.find('tbody').find('tr');
8282
var rows = [];
8383

@@ -91,11 +91,11 @@ describe('datepicker directive', function () {
9191
return rows;
9292
}
9393

94-
function clickOption( index ) {
94+
function clickOption(index) {
9595
getAllOptionsEl().eq(index).click();
9696
}
9797

98-
function getAllOptionsEl( dayMode ) {
98+
function getAllOptionsEl(dayMode) {
9999
return element.find('tbody').find('button');
100100
}
101101

@@ -108,7 +108,7 @@ describe('datepicker directive', function () {
108108
}
109109
}
110110

111-
function expectSelectedElement( index ) {
111+
function expectSelectedElement(index) {
112112
var buttons = getAllOptionsEl();
113113
angular.forEach( buttons, function( button, idx ) {
114114
expect(angular.element(button).hasClass('btn-info')).toBe( idx === index );
@@ -153,7 +153,7 @@ describe('datepicker directive', function () {
153153

154154
it('shows the label row & the correct day labels', function() {
155155
expect(getLabelsRow().css('display')).not.toBe('none');
156-
expect(getLabels()).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
156+
expect(getLabels(true)).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
157157
});
158158

159159
it('renders the calendar days correctly', function() {
@@ -211,7 +211,7 @@ describe('datepicker directive', function () {
211211
clickPreviousButton();
212212

213213
expect(getTitle()).toBe('August 2010');
214-
expect(getLabels()).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
214+
expect(getLabels(true)).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
215215
expect(getOptions(true)).toEqual([
216216
['01', '02', '03', '04', '05', '06', '07'],
217217
['08', '09', '10', '11', '12', '13', '14'],
@@ -236,7 +236,7 @@ describe('datepicker directive', function () {
236236
clickNextButton();
237237

238238
expect(getTitle()).toBe('October 2010');
239-
expect(getLabels()).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
239+
expect(getLabels(true)).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
240240
expect(getOptions(true)).toEqual([
241241
['26', '27', '28', '29', '30', '01', '02'],
242242
['03', '04', '05', '06', '07', '08', '09'],
@@ -261,7 +261,7 @@ describe('datepicker directive', function () {
261261
clickOption( 33 );
262262
expect($rootScope.date).toEqual(new Date('October 01, 2010 15:30:00'));
263263
expect(getTitle()).toBe('October 2010');
264-
expect(getLabels()).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
264+
expect(getLabels(true)).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
265265
expect(getOptions(true)).toEqual([
266266
['26', '27', '28', '29', '30', '01', '02'],
267267
['03', '04', '05', '06', '07', '08', '09'],
@@ -735,7 +735,7 @@ describe('datepicker directive', function () {
735735
});
736736

737737
it('shows the day labels rotated', function() {
738-
expect(getLabels()).toEqual(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']);
738+
expect(getLabels(true)).toEqual(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']);
739739
});
740740

741741
it('renders the calendar days correctly', function() {
@@ -755,20 +755,18 @@ describe('datepicker directive', function () {
755755
});
756756

757757
describe('attribute `show-weeks`', function () {
758-
var weekHeader, weekElement;
759758
beforeEach(function() {
760759
$rootScope.showWeeks = false;
761760
element = $compile('<datepicker ng-model="date" show-weeks="showWeeks"></datepicker>')($rootScope);
762761
$rootScope.$digest();
763-
764-
weekHeader = getLabelsRow().find('th').eq(0);
765-
weekElement = element.find('tbody').find('tr').eq(1).find('td').eq(0);
766762
});
767763

768764
it('hides week numbers based on variable', function() {
769-
expect(weekHeader.text()).toEqual('');
770-
expect(weekHeader).toBeHidden();
771-
expect(weekElement).toBeHidden();
765+
expect(getLabelsRow().find('th').length).toEqual(7);
766+
var tr = element.find('tbody').find('tr');
767+
for (var i = 0; i < 5; i++) {
768+
expect(tr.eq(i).find('td').length).toEqual(7);
769+
}
772770
});
773771
});
774772

@@ -1035,7 +1033,7 @@ describe('datepicker directive', function () {
10351033
});
10361034

10371035
it('shows day labels', function() {
1038-
expect(getLabels()).toEqual(['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']);
1036+
expect(getLabels(true)).toEqual(['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']);
10391037
});
10401038

10411039
it('changes the day format', function() {
@@ -1101,7 +1099,7 @@ describe('datepicker directive', function () {
11011099

11021100
it('changes the `starting-day` & day headers & format', function() {
11031101
expect(getLabels()).toEqual(['Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']);
1104-
expect(getOptions(true)).toEqual([
1102+
expect(getOptions(false)).toEqual([
11051103
['28', '29', '30', '31', '1', '2', '3'],
11061104
['4', '5', '6', '7', '8', '9', '10'],
11071105
['11', '12', '13', '14', '15', '16', '17'],
@@ -1112,10 +1110,10 @@ describe('datepicker directive', function () {
11121110
});
11131111

11141112
it('changes initial visibility for weeks', function() {
1115-
expect(getLabelsRow().find('th').eq(0)).toBeHidden();
1113+
expect(getLabelsRow().find('th').length).toEqual(7);
11161114
var tr = element.find('tbody').find('tr');
11171115
for (var i = 0; i < 5; i++) {
1118-
expect(tr.eq(i).find('td').eq(0)).toBeHidden();
1116+
expect(tr.eq(i).find('td').length).toEqual(7);
11191117
}
11201118
});
11211119

@@ -1212,7 +1210,7 @@ describe('datepicker directive', function () {
12121210

12131211
it('renders the calendar correctly', function() {
12141212
expect(getLabelsRow().css('display')).not.toBe('none');
1215-
expect(getLabels()).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
1213+
expect(getLabels(true)).toEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
12161214
expect(getOptions(true)).toEqual([
12171215
['29', '30', '31', '01', '02', '03', '04'],
12181216
['05', '06', '07', '08', '09', '10', '11'],
@@ -1495,23 +1493,21 @@ describe('datepicker directive', function () {
14951493
describe('attribute `datepickerOptions`', function () {
14961494

14971495
describe('show-weeks', function(){
1498-
var weekHeader, weekElement;
14991496
beforeEach(function() {
15001497
$rootScope.opts = {
15011498
'show-weeks': false
15021499
};
15031500
var wrapElement = $compile('<div><input ng-model="date" datepicker-popup datepicker-options="opts" is-open="true"></div>')($rootScope);
15041501
$rootScope.$digest();
15051502
assignElements(wrapElement);
1506-
1507-
weekHeader = getLabelsRow().find('th').eq(0);
1508-
weekElement = element.find('tbody').find('tr').eq(1).find('td').eq(0);
15091503
});
15101504

15111505
it('hides week numbers based on variable', function() {
1512-
expect(weekHeader.text()).toEqual('');
1513-
expect(weekHeader).toBeHidden();
1514-
expect(weekElement).toBeHidden();
1506+
expect(getLabelsRow().find('th').length).toEqual(7);
1507+
var tr = element.find('tbody').find('tr');
1508+
for (var i = 0; i < 5; i++) {
1509+
expect(tr.eq(i).find('td').length).toEqual(7);
1510+
}
15151511
});
15161512
});
15171513

@@ -1798,10 +1794,10 @@ describe('datepicker directive', function () {
17981794
$rootScope.$digest();
17991795
assignElements(wrapElement);
18001796

1801-
expect(getLabelsRow().find('th').eq(0)).toBeHidden();
1797+
expect(getLabelsRow().find('th').length).toEqual(7);
18021798
var tr = element.find('tbody').find('tr');
18031799
for (var i = 0; i < 5; i++) {
1804-
expect(tr.eq(i).find('td').eq(0)).toBeHidden();
1800+
expect(tr.eq(i).find('td').length).toEqual(7);
18051801
}
18061802
});
18071803

@@ -1946,10 +1942,10 @@ describe('datepicker directive', function () {
19461942
}));
19471943

19481944
it('changes initial visibility for weeks', function() {
1949-
expect(getLabelsRow().find('th').eq(0)).toBeHidden();
1945+
expect(getLabelsRow().find('th').length).toEqual(7);
19501946
var tr = element.find('tbody').find('tr');
19511947
for (var i = 0; i < 5; i++) {
1952-
expect(tr.eq(i).find('td').eq(0)).toBeHidden();
1948+
expect(tr.eq(i).find('td').length).toEqual(7);
19531949
}
19541950
});
19551951
});

Diff for: template/datepicker/day.html

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
1+
<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
22
<thead>
33
<tr>
44
<th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>
5-
<th colspan="{{5 + showWeeks}}"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>
5+
<th colspan="{{::5 + showWeeks}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>
66
<th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>
77
</tr>
88
<tr>
9-
<th ng-show="showWeeks" class="text-center"></th>
10-
<th ng-repeat="label in labels track by $index" class="text-center"><small aria-label="{{label.full}}">{{label.abbr}}</small></th>
9+
<th ng-if="showWeeks" class="text-center"></th>
10+
<th ng-repeat="label in ::labels track by $index" class="text-center"><small aria-label="{{::label.full}}">{{::label.abbr}}</small></th>
1111
</tr>
1212
</thead>
1313
<tbody>
1414
<tr ng-repeat="row in rows track by $index">
15-
<td ng-show="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td>
16-
<td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}" ng-class="dt.customClass">
17-
<button type="button" style="width:100%;" class="btn btn-default btn-sm" ng-class="{'btn-info': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{'text-muted': dt.secondary, 'text-info': dt.current}">{{dt.label}}</span></button>
15+
<td ng-if="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td>
16+
<td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{::dt.uid}}" ng-class="::dt.customClass">
17+
<button type="button" style="width:100%;" class="btn btn-default btn-sm" ng-class="{'btn-info': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="::{'text-muted': dt.secondary, 'text-info': dt.current}">{{::dt.label}}</span></button>
1818
</td>
1919
</tr>
2020
</tbody>

Diff for: template/datepicker/month.html

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
1+
<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
22
<thead>
33
<tr>
44
<th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>
5-
<th><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>
5+
<th><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>
66
<th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>
77
</tr>
88
</thead>
99
<tbody>
1010
<tr ng-repeat="row in rows track by $index">
11-
<td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">
12-
<button type="button" style="width:100%;" class="btn btn-default" ng-class="{'btn-info': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{'text-info': dt.current}">{{dt.label}}</span></button>
11+
<td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{::dt.uid}}">
12+
<button type="button" style="width:100%;" class="btn btn-default" ng-class="{'btn-info': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="::{'text-info': dt.current}">{{::dt.label}}</span></button>
1313
</td>
1414
</tr>
1515
</tbody>

Diff for: template/datepicker/year.html

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
<table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
1+
<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
22
<thead>
33
<tr>
44
<th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>
5-
<th colspan="3"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>
5+
<th colspan="3"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>
66
<th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>
77
</tr>
88
</thead>
99
<tbody>
1010
<tr ng-repeat="row in rows track by $index">
11-
<td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" aria-disabled="{{!!dt.disabled}}">
12-
<button type="button" style="width:100%;" class="btn btn-default" ng-class="{'btn-info': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{'text-info': dt.current}">{{dt.label}}</span></button>
11+
<td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{::dt.uid}}">
12+
<button type="button" style="width:100%;" class="btn btn-default" ng-class="{'btn-info': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="::{'text-info': dt.current}">{{::dt.label}}</span></button>
1313
</td>
1414
</tr>
1515
</tbody>

0 commit comments

Comments
 (0)