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

Commit 74b4bae

Browse files
committed
fix(input): fix bad char counter when value is a number. Fixes #4635.
1 parent 5d4ef55 commit 74b4bae

File tree

2 files changed

+103
-68
lines changed

2 files changed

+103
-68
lines changed

src/components/input/input.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,9 @@ function mdMaxlengthDirective($animate) {
408408
};
409409

410410
function renderCharCount(value) {
411-
charCountEl.text(( element.val() || value || '' ).length + '/' + maxlength);
411+
// Force the value into a string since it may be a number,
412+
// which does not have a length property.
413+
charCountEl.text(String(element.val() || value || '').length + '/' + maxlength);
412414
return value;
413415
}
414416
}

src/components/input/input.spec.js

+100-67
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,64 @@
11
describe('md-input-container directive', function() {
2+
var $compile, pageScope;
23

3-
beforeEach(module('material.components.input'));
4-
beforeEach(module('ngAria'));
4+
beforeEach(module('ngAria', 'material.components.input'));
5+
6+
beforeEach(inject(function($injector) {
7+
$compile = $injector.get('$compile');
8+
9+
var pageScope = $injector.get('$rootScope').$new();
10+
}));
511

612
function setup(attrs, isForm) {
713
var container;
8-
inject(function($rootScope, $compile) {
9-
container = $compile((isForm ? '<form>' : '') +
10-
'<md-input-container><input ' + (attrs || '') + '><label></label></md-input-container>' +
11-
(isForm ? '<form>' : ''))($rootScope);
12-
$rootScope.$apply();
13-
});
14+
15+
var template =
16+
'<md-input-container>' +
17+
'<input ' + (attrs || '') + '>' +
18+
'<label></label>' +
19+
'</md-input-container>';
20+
21+
if (isForm) {
22+
template = '<form>' + template + '</form>';
23+
}
24+
25+
container = $compile(template)(pageScope);
26+
27+
pageScope.$apply();
1428
return container;
1529
}
1630

17-
it('should by default show error on $touched and $invalid', inject(function($rootScope) {
31+
it('should by default show error on $touched and $invalid', function() {
1832
var el = setup('ng-model="foo"');
1933

2034
expect(el).not.toHaveClass('md-input-invalid');
2135

2236
var model = el.find('input').controller('ngModel');
2337
model.$touched = model.$invalid = true;
24-
$rootScope.$apply();
38+
pageScope.$apply();
2539

2640
expect(el).toHaveClass('md-input-invalid');
2741

2842
model.$touched = model.$invalid = false;
29-
$rootScope.$apply();
43+
pageScope.$apply();
3044
expect(el).not.toHaveClass('md-input-invalid');
31-
}));
45+
});
3246

33-
it('should show error with given md-is-error expression', inject(function($rootScope, $compile) {
34-
var el = $compile('<md-input-container md-is-error="$root.isError"><input ng-model="foo"></md-input-container>')($rootScope);
47+
it('should show error with given md-is-error expression', function() {
48+
var el = $compile(
49+
'<md-input-container md-is-error="isError">' +
50+
'<input ng-model="foo">' +
51+
'</md-input-container>')(pageScope);
3552

36-
$rootScope.$apply();
53+
pageScope.$apply();
3754
expect(el).not.toHaveClass('md-input-invalid');
3855

39-
$rootScope.$apply('isError = true');
56+
pageScope.$apply('isError = true');
4057
expect(el).toHaveClass('md-input-invalid');
4158

42-
$rootScope.$apply('isError = false');
59+
pageScope.$apply('isError = false');
4360
expect(el).not.toHaveClass('md-input-invalid');
44-
}));
61+
});
4562

4663
it('should set focus class on container', function() {
4764
var el = setup();
@@ -76,124 +93,140 @@ describe('md-input-container directive', function() {
7693
expect(el).not.toHaveClass('md-input-has-value');
7794
});
7895

79-
it('should set has-value class on container for ng-model input', inject(function($rootScope) {
80-
$rootScope.value = 'test';
81-
var el = setup('ng-model="$root.value"');
96+
it('should set has-value class on container for ng-model input', function() {
97+
pageScope.value = 'test';
98+
var el = setup('ng-model="value"');
8299
expect(el).toHaveClass('md-input-has-value');
83100

84-
$rootScope.$apply('value = "3"');
101+
pageScope.$apply('value = "3"');
85102
expect(el).toHaveClass('md-input-has-value');
86103

87-
$rootScope.$apply('value = null');
104+
pageScope.$apply('value = null');
88105
expect(el).not.toHaveClass('md-input-has-value');
89-
}));
106+
});
90107

91-
it('should match label to given input id', inject(function() {
108+
it('should match label to given input id', function() {
92109
var el = setup('id="foo"');
93110
expect(el.find('label').attr('for')).toBe('foo');
94111
expect(el.find('input').attr('id')).toBe('foo');
95-
}));
112+
});
96113

97-
it('should match label to automatic input id', inject(function() {
114+
it('should match label to automatic input id', function() {
98115
var el = setup();
99116
expect(el.find('input').attr('id')).toBeTruthy();
100117
expect(el.find('label').attr('for')).toBe(el.find('input').attr('id'));
101-
}));
118+
});
102119

103120
describe('md-maxlength', function() {
104121
function getCharCounter(el) {
105122
return angular.element(el[0].querySelector('.md-char-counter'));
106123
}
107124

108-
it('should work with a constant', inject(function($rootScope, $compile) {
109-
var el = $compile('<form name="form">' +
110-
' <md-input-container>' +
111-
' <input md-maxlength="5" ng-model="foo" name="foo">' +
112-
' </md-input-container>' +
113-
'</form>')($rootScope);
114-
$rootScope.$apply();
115-
expect($rootScope.form.foo.$error['md-maxlength']).toBeFalsy();
125+
it('should work with a constant', function() {
126+
var el = $compile(
127+
'<form name="form">' +
128+
'<md-input-container>' +
129+
'<input md-maxlength="5" ng-model="foo" name="foo">' +
130+
'</md-input-container>' +
131+
'</form>')(pageScope);
132+
133+
pageScope.$apply();
134+
expect(pageScope.form.foo.$error['md-maxlength']).toBeFalsy();
116135
expect(getCharCounter(el).text()).toBe('0/5');
117136

118-
$rootScope.$apply('foo = "abcde"');
119-
expect($rootScope.form.foo.$error['md-maxlength']).toBeFalsy();
137+
pageScope.$apply('foo = "abcde"');
138+
expect(pageScope.form.foo.$error['md-maxlength']).toBeFalsy();
120139
expect(getCharCounter(el).text()).toBe('5/5');
121140

122-
$rootScope.$apply('foo = "abcdef"');
141+
pageScope.$apply('foo = "abcdef"');
123142
el.find('input').triggerHandler('input');
124-
expect($rootScope.form.foo.$error['md-maxlength']).toBe(true);
143+
expect(pageScope.form.foo.$error['md-maxlength']).toBe(true);
125144
expect(getCharCounter(el).text()).toBe('6/5');
126145

127-
$rootScope.$apply('foo = "abc"');
146+
pageScope.$apply('foo = "abc"');
128147
el.find('input').triggerHandler('input');
129-
expect($rootScope.form.foo.$error['md-maxlength']).toBeFalsy();
148+
expect(pageScope.form.foo.$error['md-maxlength']).toBeFalsy();
130149
expect(getCharCounter(el).text()).toBe('3/5');
131-
}));
150+
});
151+
152+
it('should render correct character count when value is a number', function() {
153+
var template =
154+
'<md-input-container>' +
155+
'<input ng-model="item.numberValue" md-maxlength="6">' +
156+
'</md-input-container>';
157+
var element = $compile(template)(pageScope);
158+
pageScope.$apply();
159+
160+
pageScope.item = {numberValue: 456};
161+
pageScope.$apply();
162+
163+
expect(getCharCounter(element).text()).toBe('3/6');
164+
});
132165

133-
it('should add and remove maxlength element & error with expression', inject(function($rootScope, $compile) {
166+
it('should add and remove maxlength element & error with expression', function() {
134167
var el = $compile('<form name="form">' +
135168
' <md-input-container>' +
136169
' <input md-maxlength="max" ng-model="foo" name="foo">' +
137170
' </md-input-container>' +
138-
'</form>')($rootScope);
171+
'</form>')(pageScope);
139172

140-
$rootScope.$apply();
141-
expect($rootScope.form.foo.$error['md-maxlength']).toBeFalsy();
173+
pageScope.$apply();
174+
expect(pageScope.form.foo.$error['md-maxlength']).toBeFalsy();
142175
expect(getCharCounter(el).length).toBe(0);
143176

144-
$rootScope.$apply('max = 5');
145-
$rootScope.$apply('foo = "abcdef"');
146-
expect($rootScope.form.foo.$error['md-maxlength']).toBeTruthy();
177+
pageScope.$apply('max = 5');
178+
pageScope.$apply('foo = "abcdef"');
179+
expect(pageScope.form.foo.$error['md-maxlength']).toBeTruthy();
147180
expect(getCharCounter(el).length).toBe(1);
148181
expect(getCharCounter(el).text()).toBe('6/5');
149182

150-
$rootScope.$apply('max = -1');
151-
$rootScope.$apply('foo = "abcdefg"');
152-
expect($rootScope.form.foo.$error['md-maxlength']).toBeFalsy();
183+
pageScope.$apply('max = -1');
184+
pageScope.$apply('foo = "abcdefg"');
185+
expect(pageScope.form.foo.$error['md-maxlength']).toBeFalsy();
153186
expect(getCharCounter(el).length).toBe(0);
154-
}));
187+
});
155188
});
156189

157-
it('should put placeholder into a label element', inject(function($rootScope, $compile) {
158-
var el = $compile('<md-input-container><input ng-model="foo" placeholder="some placeholder"></md-input-container>')($rootScope);
190+
it('should put placeholder into a label element', function() {
191+
var el = $compile('<md-input-container><input ng-model="foo" placeholder="some placeholder"></md-input-container>')(pageScope);
159192
var placeholder = el[0].querySelector('.md-placeholder');
160193
var label = el.find('label')[0];
161194

162195
expect(el.find('input')[0].hasAttribute('placeholder')).toBe(false);
163196
expect(label).toBeTruthy();
164197
expect(label.textContent).toEqual('some placeholder');
165-
}));
198+
});
166199

167-
it('should ignore placeholder when a label element is present', inject(function($rootScope, $compile) {
200+
it('should ignore placeholder when a label element is present', function() {
168201
var el = $compile(
169202
'<md-input-container>' +
170203
' <label>Hello</label>' +
171204
' <input ng-model="foo" placeholder="some placeholder" />' +
172205
'</md-input-container>'
173-
)($rootScope);
206+
)(pageScope);
174207

175208
var label = el.find('label')[0];
176209

177210
expect(el.find('input')[0].hasAttribute('placeholder')).toBe(true);
178211
expect(label).toBeTruthy();
179212
expect(label.textContent).toEqual('Hello');
180-
}));
213+
});
181214

182-
it('should put an aria-label on the input when no label is present', inject(function($rootScope, $compile) {
215+
it('should put an aria-label on the input when no label is present', function() {
183216
var el = $compile('<form name="form">' +
184217
' <md-input-container md-no-float>' +
185218
' <input placeholder="baz" md-maxlength="max" ng-model="foo" name="foo">' +
186219
' </md-input-container>' +
187-
'</form>')($rootScope);
220+
'</form>')(pageScope);
188221

189-
$rootScope.$apply();
222+
pageScope.$apply();
190223

191224
var input = el.find('input');
192225
expect(input.attr('aria-label')).toBe('baz');
193-
}));
226+
});
194227

195-
it('should put the container in "has value" state when input has a static value', inject(function($rootScope, $compile) {
196-
var scope = $rootScope.$new();
228+
it('should put the container in "has value" state when input has a static value', function() {
229+
var scope = pageScope.$new();
197230
var template =
198231
'<md-input-container>' +
199232
'<label>Name</label>' +
@@ -204,5 +237,5 @@ describe('md-input-container directive', function() {
204237
scope.$apply();
205238

206239
expect(element.hasClass('md-input-has-value')).toBe(true);
207-
}));
240+
});
208241
});

0 commit comments

Comments
 (0)