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

Commit 2b41a58

Browse files
gkalpaklgalfaso
authored andcommitted
feat(ngPluralize): add support for count to be a one-time expression
Closes #10004
1 parent 637c020 commit 2b41a58

File tree

2 files changed

+103
-19
lines changed

2 files changed

+103
-19
lines changed

src/ng/directive/ngPluralize.js

+31-19
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,9 @@
173173
</example>
174174
*/
175175
var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
176-
var BRACE = /{}/g;
176+
var BRACE = /{}/g,
177+
IS_WHEN = /^when(Minus)?(.+)$/;
178+
177179
return {
178180
restrict: 'EA',
179181
link: function(scope, element, attr) {
@@ -184,34 +186,44 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
184186
whensExpFns = {},
185187
startSymbol = $interpolate.startSymbol(),
186188
endSymbol = $interpolate.endSymbol(),
187-
isWhen = /^when(Minus)?(.+)$/;
189+
braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,
190+
watchRemover = angular.noop,
191+
lastCount;
188192

189193
forEach(attr, function(expression, attributeName) {
190-
if (isWhen.test(attributeName)) {
191-
whens[lowercase(attributeName.replace('when', '').replace('Minus', '-'))] =
192-
element.attr(attr.$attr[attributeName]);
194+
var tmpMatch = IS_WHEN.exec(attributeName);
195+
if (tmpMatch) {
196+
var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);
197+
whens[whenKey] = element.attr(attr.$attr[attributeName]);
193198
}
194199
});
195200
forEach(whens, function(expression, key) {
196-
whensExpFns[key] =
197-
$interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +
198-
offset + endSymbol));
201+
whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));
202+
199203
});
200204

201-
scope.$watch(function ngPluralizeWatch() {
202-
var value = parseFloat(scope.$eval(numberExp));
205+
scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {
206+
var count = parseFloat(newVal);
207+
var countIsNaN = isNaN(count);
203208

204-
if (!isNaN(value)) {
205-
//if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
206-
//check it against pluralization rules in $locale service
207-
if (!(value in whens)) value = $locale.pluralCat(value - offset);
208-
return whensExpFns[value](scope);
209-
} else {
210-
return '';
209+
if (!countIsNaN && !(count in whens)) {
210+
// If an explicit number rule such as 1, 2, 3... is defined, just use it.
211+
// Otherwise, check it against pluralization rules in $locale service.
212+
count = $locale.pluralCat(count - offset);
213+
}
214+
215+
// If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
216+
// In JS `NaN !== NaN`, so we have to exlicitly check.
217+
if ((count !== lastCount) && !(countIsNaN && isNaN(lastCount))) {
218+
watchRemover();
219+
watchRemover = scope.$watch(whensExpFns[count], updateElementText);
220+
lastCount = count;
211221
}
212-
}, function ngPluralizeWatchAction(newVal) {
213-
element.text(newVal);
214222
});
223+
224+
function updateElementText(newText) {
225+
element.text(newText || '');
226+
}
215227
}
216228
};
217229
}];

test/ng/directive/ngPluralizeSpec.js

+72
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,76 @@ describe('ngPluralize', function() {
242242
});
243243
});
244244
});
245+
246+
247+
describe('bind-once', function() {
248+
249+
it('should support for `count` to be a one-time expression',
250+
inject(function($compile, $rootScope) {
251+
element = $compile(
252+
'<ng:pluralize count="::email"' +
253+
"when=\"{'one': 'You have one new email'," +
254+
"'other': 'You have {} new emails'}\">" +
255+
'</ng:pluralize>')($rootScope);
256+
elementAlt = $compile(
257+
'<ng:pluralize count="::email" ' +
258+
"when-one='You have one new email' " +
259+
"when-other='You have {} new emails'>" +
260+
'</ng:pluralize>')($rootScope);
261+
262+
$rootScope.email = undefined;
263+
$rootScope.$digest();
264+
expect(element.text()).toBe('');
265+
expect(elementAlt.text()).toBe('');
266+
267+
$rootScope.email = 3;
268+
$rootScope.$digest();
269+
expect(element.text()).toBe('You have 3 new emails');
270+
expect(elementAlt.text()).toBe('You have 3 new emails');
271+
272+
$rootScope.email = 2;
273+
$rootScope.$digest();
274+
expect(element.text()).toBe('You have 3 new emails');
275+
expect(elementAlt.text()).toBe('You have 3 new emails');
276+
277+
$rootScope.email = 1;
278+
$rootScope.$digest();
279+
expect(element.text()).toBe('You have 3 new emails');
280+
expect(elementAlt.text()).toBe('You have 3 new emails');
281+
})
282+
);
283+
284+
285+
it('should still update other embedded expressions',
286+
inject(function($compile, $rootScope) {
287+
element = $compile(
288+
'<ng:pluralize count="::email"' +
289+
"when=\"{'one': 'You, {{user}}, have one new email'," +
290+
"'other': 'You, {{user}}, have {} new emails'}\">" +
291+
'</ng:pluralize>')($rootScope);
292+
elementAlt = $compile(
293+
'<ng:pluralize count="::email" ' +
294+
"when-one='You, {{user}}, have one new email' " +
295+
"when-other='You, {{user}}, have {} new emails'>" +
296+
'</ng:pluralize>')($rootScope);
297+
298+
$rootScope.user = 'Lucas';
299+
$rootScope.email = undefined;
300+
$rootScope.$digest();
301+
expect(element.text()).toBe('');
302+
expect(elementAlt.text()).toBe('');
303+
304+
$rootScope.email = 3;
305+
$rootScope.$digest();
306+
expect(element.text()).toBe('You, Lucas, have 3 new emails');
307+
expect(elementAlt.text()).toBe('You, Lucas, have 3 new emails');
308+
309+
$rootScope.user = 'Pete';
310+
$rootScope.email = 2;
311+
$rootScope.$digest();
312+
expect(element.text()).toBe('You, Pete, have 3 new emails');
313+
expect(elementAlt.text()).toBe('You, Pete, have 3 new emails');
314+
})
315+
);
316+
});
245317
});

0 commit comments

Comments
 (0)