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

Commit bd78f49

Browse files
author
Andy Tang
committed
Added new directive mdTextarea
- Extracted the link function of the `mdInputDirective` to reuse it for the `mdTextareaDirective` -`mdTextarea` is configurable with `rows` and `cols`, but behaves the same as `mdInput`
1 parent ab81a22 commit bd78f49

File tree

5 files changed

+379
-217
lines changed

5 files changed

+379
-217
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ themes/_default-theme.scss
1212
/vendor
1313

1414
.polymer-qp
15+
16+
atlassian-ide-plugin.xml
17+
*.iml

src/components/textField/demoBasicUsage/index.html

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
21
<div ng-controller="DemoController" layout="vertical">
32
<md-content md-theme="light-blue-dark">
43
<form style="padding: 20px;">
54
<div class="row">
6-
<md-text-float label="Title" ng-model="user.title" ></md-text-float>
7-
<md-text-float label="eMail" ng-model="user.email" type="email" ></md-text-float>
5+
<md-text-float label="Title" ng-model="user.title"></md-text-float>
6+
<md-text-float label="eMail" ng-model="user.email" type="email"></md-text-float>
87
</div>
98
</form>
109
</md-content>
1110

1211
<md-content>
1312
<form style="padding: 20px;">
14-
<md-text-float label="Company" ng-model="user.company" disabled > </md-text-float>
13+
<md-text-float label="Company" ng-model="user.company" disabled></md-text-float>
1514
<div class="row">
16-
<md-text-float label="FirstName" ng-model="user.firstName" > </md-text-float>
17-
<md-text-float label="LastName" ng-model="user.lastName" class="long"> </md-text-float>
15+
<md-text-float label="FirstName" ng-model="user.firstName"></md-text-float>
16+
<md-text-float label="LastName" ng-model="user.lastName" class="long"></md-text-float>
1817
</div>
19-
<md-text-float label="Address" ng-model="user.address" > </md-text-float>
18+
<md-text-float label="Address" ng-model="user.address"></md-text-float>
2019
<div class="row">
21-
<md-text-float label="City" ng-model="user.city" > </md-text-float>
22-
<md-text-float label="State" ng-model="user.state" > </md-text-float>
23-
<md-text-float label="Postal Code" ng-model="user.postalCode" > </md-text-float>
20+
<md-text-float label="City" ng-model="user.city"></md-text-float>
21+
<md-text-float label="State" ng-model="user.state"></md-text-float>
22+
<md-text-float label="Postal Code" ng-model="user.postalCode"></md-text-float>
2423
</div>
25-
<md-text-float label="Country" ng-model="user.country" disabled > </md-text-float>
24+
<md-text-float label="Country" ng-model="user.country" disabled></md-text-float>
25+
<md-textarea-float label="Intro" ng-model="user.intro" rows="4" cols="50"></md-textarea-float>
2626
</form>
2727
</md-content>
2828

src/components/textField/demoBasicUsage/script.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
21
angular.module('textFieldDemo1', ['ngMaterial'])
32

4-
/**
5-
* Simple controller to build a `user` data model
6-
* that will be used to databinding with `<tf-float>` directives
7-
*/
8-
.controller('DemoController', function($scope) {
3+
/**
4+
* Simple controller to build a `user` data model
5+
* that will be used to databinding with `<tf-float>` directives
6+
*/
7+
.controller('DemoController', function ($scope) {
98
$scope.user = {
10-
title: "Technical Program Manager",
11-
email: "ipsum@lorem.com",
12-
firstName: "Naomi",
13-
lastName: "" ,
14-
company: "Google" ,
15-
address: "1600 Amphitheatre Pkwy" ,
16-
city: "Mountain View" ,
17-
state: "CA" ,
18-
country: "USA" ,
19-
postalCode : "94043"
9+
title: "Technical Program Manager",
10+
email: "ipsum@lorem.com",
11+
firstName: "Naomi",
12+
lastName: "",
13+
company: "Google",
14+
address: "1600 Amphitheatre Pkwy",
15+
city: "Mountain View",
16+
state: "CA",
17+
country: "USA",
18+
postalCode: "94043",
19+
intro: ""
2020
};
2121
});
2222

src/components/textField/textField.js

Lines changed: 185 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
* Form
66
*/
77
angular.module('material.components.textField', ['material.core', 'material.services.theming'])
8-
.directive('mdInputGroup', [ mdInputGroupDirective ])
9-
.directive('mdInput', ['$mdUtil', mdInputDirective ])
10-
.directive('mdTextFloat', [ '$mdTheming', '$mdUtil', mdTextFloatDirective ]);
11-
8+
.directive('mdInputGroup', [ mdInputGroupDirective ])
9+
.directive('mdInput', ['$mdUtil', mdInputDirective ])
10+
.directive('mdTextarea', ['$mdUtil', mdTextareaDirective])
11+
.directive('mdTextFloat', [ '$mdTheming', '$mdUtil', mdTextFloatDirective ])
12+
.directive('mdTextareaFloat', [ '$mdTheming', '$mdUtil', mdTextareaFloatDirective ]);
1213

1314

1415
/**
@@ -41,21 +42,21 @@ function mdTextFloatDirective($mdTheming, $mdUtil) {
4142
return {
4243
restrict: 'E',
4344
replace: true,
44-
scope : {
45-
fid : '@?',
46-
label : '@?',
47-
value : '=ngModel'
45+
scope: {
46+
fid: '@?',
47+
label: '@?',
48+
value: '=ngModel'
4849
},
49-
compile : function(element, attr) {
50+
compile: function (element, attr) {
5051

51-
if ( angular.isUndefined(attr.fid) ) {
52+
if (angular.isUndefined(attr.fid)) {
5253
attr.fid = $mdUtil.nextUid();
5354
}
5455

5556
return {
56-
pre : function(scope, element, attrs) {
57+
pre: function (scope, element, attrs) {
5758
// transpose `disabled` flag
58-
if ( angular.isDefined(attrs.disabled) ) {
59+
if (angular.isDefined(attrs.disabled)) {
5960
element.attr('disabled', true);
6061
scope.isDisabled = true;
6162
}
@@ -64,17 +65,80 @@ function mdTextFloatDirective($mdTheming, $mdUtil) {
6465
element.removeAttr('type');
6566

6667
// transpose optional `class` settings
67-
element.attr('class', attrs.class );
68+
element.attr('class', attrs.class);
69+
70+
},
71+
post: $mdTheming
72+
};
73+
},
74+
template: '<md-input-group ng-disabled="isDisabled" tabindex="-1">' +
75+
' <label for="{{fid}}" >{{label}}</label>' +
76+
' <md-input id="{{fid}}" ng-model="value" type="{{inputType}}"></md-input>' +
77+
'</md-input-group>'
78+
};
79+
}
80+
81+
/**
82+
* @ngdoc directive
83+
* @name mdTextareaFloat
84+
* @module material.components.textField
85+
*
86+
* @restrict E
87+
*
88+
* @description
89+
* Use the `<md-textarea-float>` directive to quickly construct `Floating Label` textarea fields
90+
*
91+
* @param {string} fid Attribute used for accessibility link pairing between the Label and Input elements
92+
* @param {string=} rows Optional value to define the amount of rows.
93+
* @param {string=} cols Optional value to define the amount of cols.
94+
* @param {string} label Attribute to specify the input text field hint.
95+
* @param {string=} ng-model Optional value to assign as existing input text string
96+
*
97+
* @usage
98+
* <hljs lang="html">
99+
* <md-textarea-float label="Intro" ng-model="user.intro" > </md-textarea-float>
100+
*
101+
* <!-- Specify the amount of rows and cols. -->
102+
* <md-textarea-float label="Company" ng-model="user.company" rows="4" cols="50" > </md-textarea-float>
103+
* </hljs>
104+
*/
105+
function mdTextareaFloatDirective($mdTheming, $mdUtil) {
106+
return {
107+
restrict: 'E',
108+
replace: true,
109+
scope: {
110+
fid: '@?',
111+
label: '@?',
112+
rows: '@?',
113+
cols: '@?',
114+
value: '=ngModel'
115+
},
116+
compile: function (element, attr) {
117+
118+
if (angular.isUndefined(attr.fid)) {
119+
attr.fid = $mdUtil.nextUid();
120+
}
121+
122+
return {
123+
pre: function (scope, element, attrs) {
124+
// transpose `disabled` flag
125+
if (angular.isDefined(attrs.disabled)) {
126+
element.attr('disabled', true);
127+
scope.isDisabled = true;
128+
}
129+
130+
// transpose optional `class` settings
131+
element.attr('class', attrs.class);
68132

69133
},
70134
post: $mdTheming
71135
};
72136
},
73-
template:
74-
'<md-input-group ng-disabled="isDisabled" tabindex="-1">' +
75-
' <label for="{{fid}}" >{{label}}</label>' +
76-
' <md-input id="{{fid}}" ng-model="value" type="{{inputType}}"></md-input>' +
77-
'</md-input-group>'
137+
template: '<md-input-group ng-disabled="isDisabled" tabindex="-1">' +
138+
' <label for="{{fid}}" >{{label}}</label>' +
139+
' <md-textarea id="{{fid}}" ng-model="value" ' +
140+
' rows="{{rows}}" cols="{{cols}}"></md-textarea>' +
141+
'</md-input-group>'
78142
};
79143
}
80144

@@ -99,12 +163,12 @@ function mdTextFloatDirective($mdTheming, $mdUtil) {
99163
function mdInputGroupDirective() {
100164
return {
101165
restrict: 'CE',
102-
controller: ['$element', function($element) {
103-
this.setFocused = function(isFocused) {
166+
controller: ['$element', function ($element) {
167+
this.setFocused = function (isFocused) {
104168
$element.toggleClass('md-input-focused', !!isFocused);
105169
};
106-
this.setHasValue = function(hasValue) {
107-
$element.toggleClass('md-input-has-value', hasValue );
170+
this.setHasValue = function (hasValue) {
171+
$element.toggleClass('md-input-has-value', hasValue);
108172
};
109173
}]
110174
};
@@ -137,59 +201,111 @@ function mdInputDirective($mdUtil) {
137201
replace: true,
138202
template: '<input >',
139203
require: ['^?mdInputGroup', '?ngModel'],
140-
link: function(scope, element, attr, ctrls) {
141-
var inputGroupCtrl = ctrls[0];
142-
var ngModelCtrl = ctrls[1];
143-
if (!inputGroupCtrl) {
144-
return;
145-
}
204+
link: function mdInputDirectiveLink(scope, element, attr, ctrls) {
205+
linkBehaviours(scope, element, ctrls, $mdUtil);
146206

147-
// scan for disabled and transpose the `type` value to the <input> element
148-
var isDisabled = $mdUtil.isParentDisabled(element);
149-
150-
element.attr('tabindex', isDisabled ? -1 : 0 );
151-
element.attr('aria-disabled', isDisabled ? 'true' : 'false');
152-
element.attr('type', attr.type || element.parent().attr('type') || "text" );
153-
154-
// When the input value changes, check if it "has" a value, and
155-
// set the appropriate class on the input group
156-
if (ngModelCtrl) {
157-
//Add a $formatter so we don't use up the render function
158-
ngModelCtrl.$formatters.push(function(value) {
159-
inputGroupCtrl.setHasValue( isNotEmpty(value) );
160-
return value;
161-
});
162-
}
207+
element.attr('type', attr.type || element.parent().attr('type') || "text");
208+
}
209+
};
210+
}
163211

164-
element.on('input', function() {
165-
inputGroupCtrl.setHasValue( isNotEmpty() );
166-
});
167-
168-
// When the input focuses, add the focused class to the group
169-
element.on('focus', function(e) {
170-
inputGroupCtrl.setFocused(true);
171-
});
172-
// When the input blurs, remove the focused class from the group
173-
element.on('blur', function(e) {
174-
inputGroupCtrl.setFocused(false);
175-
inputGroupCtrl.setHasValue( isNotEmpty() );
176-
});
177-
178-
scope.$on('$destroy', function() {
179-
inputGroupCtrl.setFocused(false);
180-
inputGroupCtrl.setHasValue(false);
181-
});
182-
183-
184-
function isNotEmpty(value) {
185-
value = angular.isUndefined(value) ? element.val() : value;
186-
return (angular.isDefined(value) && (value!==null) &&
187-
(value.toString().trim() != ""));
188-
}
212+
/*
213+
* @private
214+
*
215+
* @ngdoc directive
216+
* @name mdTextarea
217+
* @module material.components.textField
218+
*
219+
* @restrict E
220+
*
221+
* @description
222+
* Use the `<md-textarea>` directive as elements within a `<md-input-group>` container
223+
*
224+
* @usage
225+
* <hljs lang="html">
226+
* <md-input-group ng-disabled="user.isLocked">
227+
* <label for="i1">Intro</label>
228+
* <md-textarea id="i1" ng-model="user.intro"></md-textarea>
229+
* </md-input-group>
230+
* </hljs>
231+
*/
232+
function mdTextareaDirective($mdUtil) {
233+
return {
234+
restrict: 'E',
235+
replace: true,
236+
template: '<textarea >',
237+
require: ['^?mdInputGroup', '?ngModel'],
238+
link: function mdInputDirectiveLink(scope, element, attr, ctrls) {
239+
linkBehaviours(scope, element, ctrls, $mdUtil);
240+
241+
element.attr('rows', attr.rows || element.parent().attr('rows') || "8");
242+
element.attr('cols', attr.cols || element.parent().attr('cols') || "100");
189243
}
190244
};
191245
}
192246

247+
/*
248+
* @private
249+
*
250+
* @ngdoc directive
251+
* @name mdTextarea
252+
* @module material.components.textField
253+
* @function
254+
*
255+
* @description
256+
* The link function used in the mdInput and mdTextarea
257+
*
258+
*/
259+
function linkBehaviours(scope, element, ctrls, $mdUtil) {
260+
var inputGroupCtrl = ctrls[0];
261+
var ngModelCtrl = ctrls[1];
262+
if (!inputGroupCtrl) {
263+
return;
264+
}
265+
266+
// scan for disabled and transpose the `type` value to the <input> element
267+
var isDisabled = $mdUtil.isParentDisabled(element);
268+
269+
element.attr('tabindex', isDisabled ? -1 : 0);
270+
element.attr('aria-disabled', isDisabled ? 'true' : 'false');
271+
272+
// When the input value changes, check if it "has" a value, and
273+
// set the appropriate class on the input group
274+
if (ngModelCtrl) {
275+
//Add a $formatter so we don't use up the render function
276+
ngModelCtrl.$formatters.push(function (value) {
277+
inputGroupCtrl.setHasValue(isNotEmpty(value));
278+
return value;
279+
});
280+
}
281+
282+
element.on('input', function () {
283+
inputGroupCtrl.setHasValue(isNotEmpty());
284+
});
285+
286+
// When the input focuses, add the focused class to the group
287+
element.on('focus', function (e) {
288+
inputGroupCtrl.setFocused(true);
289+
});
290+
// When the input blurs, remove the focused class from the group
291+
element.on('blur', function (e) {
292+
inputGroupCtrl.setFocused(false);
293+
inputGroupCtrl.setHasValue(isNotEmpty());
294+
});
295+
296+
scope.$on('$destroy', function () {
297+
inputGroupCtrl.setFocused(false);
298+
inputGroupCtrl.setHasValue(false);
299+
});
300+
301+
302+
function isNotEmpty(value) {
303+
value = angular.isUndefined(value) ? element.val() : value;
304+
return (angular.isDefined(value) && (value !== null) &&
305+
(value.toString().trim() != ""));
306+
}
307+
}
308+
193309

194310

195311

0 commit comments

Comments
 (0)