Skip to content
This repository was archived by the owner on Jan 22, 2018. It is now read-only.

Commit 11c2c54

Browse files
author
Kamil Kisiela
committed
feat(input): add min, max and step attributes
only if type is 'number'
1 parent 973311a commit 11c2c54

File tree

2 files changed

+141
-17
lines changed

2 files changed

+141
-17
lines changed

src/types/input/input.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,48 @@
11
import template from './input.html';
2+
import { ngModelAttrsTransformer } from './../../helpers';
23

34
export default (formlyConfigProvider) => {
5+
function onlyNumberType(check) {
6+
return check.shape.onlyIf(['type'], check.oneOf(['number'])).optional;
7+
}
8+
49
formlyConfigProvider.setType({
510
template,
611
name: 'input',
712
wrapper: ['label', 'messages', 'inputContainer'],
813
defaultOptions: {
14+
templateOptions: {
15+
type: 'text'
16+
},
917
ngModelAttrs: {
1018
mdMaxlength: {
1119
bound: 'md-maxlength'
1220
}
1321
}
22+
},
23+
apiCheck: (check) => {
24+
return {
25+
templateOptions: {
26+
step: onlyNumberType(check),
27+
min: onlyNumberType(check),
28+
max: onlyNumberType(check)
29+
}
30+
};
1431
}
1532
});
33+
34+
35+
if (!angular.isArray(formlyConfigProvider.extras.fieldTransform)) {
36+
formlyConfigProvider.extras.fieldTransform = [];
37+
}
38+
39+
// add only step attribute because min and max are both built-in
40+
formlyConfigProvider.extras.fieldTransform.push((fields) => {
41+
return ngModelAttrsTransformer(fields, (field) => (
42+
field.type === 'input' &&
43+
field.templateOptions.type === 'number'
44+
), 'step', {
45+
attribute: 'step'
46+
});
47+
});
1648
};

tests/types/input-spec.js

Lines changed: 109 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,122 @@ describe('formlyMaterial - input type', () => {
4444
$compile = _$compile_;
4545
$rootScope = _$rootScope_;
4646
});
47-
48-
compile();
4947
});
5048

51-
it('should be input element', () => {
52-
expect(element[0].nodeName).toBe('INPUT');
53-
});
49+
describe('basics', () => {
50+
beforeEach(() => {
51+
compile();
52+
});
5453

55-
it('should have proper type attribute', () => {
56-
expect(element.attr('type')).toBe(field.templateOptions.type);
57-
});
54+
it('should be input element', () => {
55+
expect(element[0].nodeName).toBe('INPUT');
56+
});
5857

59-
it('should have messages wrapper', () => {
60-
expect(form.find('[ng-messages]').length).toBe(1);
61-
});
58+
it('should have proper type attribute', () => {
59+
expect(element.attr('type')).toBe(field.templateOptions.type);
60+
});
6261

63-
it('should have label wrapper', () => {
64-
const label = form.find('label');
62+
it('should have messages wrapper', () => {
63+
expect(form.find('[ng-messages]').length).toBe(1);
64+
});
65+
66+
it('should have label wrapper', () => {
67+
const label = form.find('label');
68+
69+
expect(label.length).toBe(1);
70+
expect(label.html()).toContain(field.templateOptions.label);
71+
});
6572

66-
expect(label.length).toBe(1);
67-
expect(label.html()).toContain(field.templateOptions.label);
73+
it('should have inputContainer wrapper', () => {
74+
expect(form.find('md-input-container').length).toBe(1);
75+
});
6876
});
6977

70-
it('should have inputContainer wrapper', () => {
71-
expect(form.find('md-input-container').length).toBe(1);
78+
describe('number type specific', () => {
79+
describe('step attribute', () => {
80+
it('should fail on non number type', () => {
81+
expect(() => {
82+
compile({
83+
templateOptions: {
84+
type: 'text',
85+
step: 2
86+
},
87+
apiCheckFunction: 'throw'
88+
});
89+
}).toThrowError(Error, /step/i);
90+
});
91+
92+
it('should not be available on non number type', () => {
93+
compile({
94+
templateOptions: {
95+
type: 'text',
96+
step: 2
97+
}
98+
});
99+
100+
expect(element.attr('step')).toBeUndefined();
101+
});
102+
103+
it('should be available on number type', () => {
104+
compile({
105+
templateOptions: {
106+
type: 'number',
107+
step: 2
108+
}
109+
});
110+
111+
expect(parseInt(element.attr('step'))).toEqual(field.templateOptions.step);
112+
});
113+
});
114+
115+
describe('min attribute', () => {
116+
it('should fail on non number type', () => {
117+
expect(() => {
118+
compile({
119+
templateOptions: {
120+
type: 'text',
121+
min: 2
122+
},
123+
apiCheckFunction: 'throw'
124+
});
125+
}).toThrowError(Error, /min/i);
126+
});
127+
128+
it('should be available on number type', () => {
129+
compile({
130+
templateOptions: {
131+
type: 'number',
132+
min: 2
133+
}
134+
});
135+
136+
expect(parseInt(element.attr('min'))).toEqual(field.templateOptions.min);
137+
});
138+
});
139+
140+
describe('max attribute', () => {
141+
it('should fail on non number type', () => {
142+
expect(() => {
143+
compile({
144+
templateOptions: {
145+
type: 'text',
146+
max: 2
147+
},
148+
apiCheckFunction: 'throw'
149+
});
150+
}).toThrowError(Error, /max/i);
151+
});
152+
153+
it('should be available on number type', () => {
154+
compile({
155+
templateOptions: {
156+
type: 'number',
157+
max: 2
158+
}
159+
});
160+
161+
expect(parseInt(element.attr('max'))).toEqual(field.templateOptions.max);
162+
});
163+
});
72164
});
73165
});

0 commit comments

Comments
 (0)