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

Commit c441157

Browse files
Sérgio Gomessgomes
authored andcommitted
feat(form-field): Make form field labels trigger input ripples.
This PR creates MDCFormField, which manages the runtime relationship between an input element and its label, enabling label events to trigger input ripples. Implements #9.
1 parent 494c10b commit c441157

File tree

13 files changed

+449
-7
lines changed

13 files changed

+449
-7
lines changed

demos/checkbox.html

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,16 @@ <h2>Dark Theme</h2>
141141
(function(global) {
142142
'use strict';
143143
var MDCCheckbox = global.mdc.checkbox.MDCCheckbox;
144-
var checkbox = new MDCCheckbox(document.getElementById('mdc-js-checkbox'));
144+
var MDCFormField = global.mdc.formField.MDCFormField;
145+
146+
var checkbox = document.getElementById('mdc-js-checkbox');
147+
var checkboxInstance = new MDCCheckbox(document.getElementById('mdc-js-checkbox'));
148+
149+
var formField = checkbox.parentElement;
150+
var formFieldInstance = new MDCFormField(formField);
151+
152+
formFieldInstance.input = checkboxInstance;
153+
145154
document.getElementById('make-ind').addEventListener('click', function() {
146155
checkbox.indeterminate = true;
147156
});

demos/radio.html

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,18 @@ <h2>Disabled</h2>
172172
<script>
173173
(function(global) {
174174
'use strict';
175-
var radios = document.querySelectorAll('.mdc-radio:not([data-demo-no-js])');
176-
for (var i = 0, radio; radio = radios[i]; i++) {
177-
global.mdc.radio.MDCRadio.attachTo(radio);
175+
var MDCFormField = global.mdc.formField.MDCFormField;
176+
var MDCRadio = global.mdc.radio.MDCRadio;
177+
178+
var formFields = document.querySelectorAll('.mdc-form-field');
179+
for (var i = 0, formField; formField = formFields[i]; i++) {
180+
var formFieldInstance = new MDCFormField(formField);
181+
182+
var radio = formField.querySelector('.mdc-radio:not([data-demo-no-js])');
183+
if (radio) {
184+
var radioInstance = new MDCRadio(radio);
185+
formFieldInstance.input = radioInstance;
186+
}
178187
}
179188
})(this);
180189
</script>

packages/material-components-web/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import * as base from '@material/base';
1818
import * as checkbox from '@material/checkbox';
19+
import * as formField from '@material/form-field';
1920
import * as iconToggle from '@material/icon-toggle';
2021
import * as radio from '@material/radio';
2122
import * as ripple from '@material/ripple';
@@ -41,6 +42,7 @@ autoInit.register('MDCSelect', select.MDCSelect);
4142
export {
4243
base,
4344
checkbox,
45+
formField,
4446
iconToggle,
4547
radio,
4648
ripple,

packages/mdc-checkbox/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ export class MDCCheckbox extends MDCComponent {
7878
});
7979
}
8080

81+
get ripple() {
82+
return this.ripple_;
83+
}
84+
8185
get checked() {
8286
return this.foundation_.isChecked();
8387
}

packages/mdc-form-field/README.md

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
# MDC Form Field
22

33
MDC Form Field provides an `mdc-form-field` helper class for easily making theme-aware, RTL-aware
4-
form field + label combos.
4+
form field + label combos. It also provides an `MDCFormField` class for easily making input ripples
5+
respond to label events.
56

67
## Installation
78

89
```
910
npm install --save @material/form-field
1011
```
1112

12-
## Usage
13+
## CSS Usage
1314

1415
The `mdc-form-field` class can be used as a wrapper element with any `input` + `label` combo:
1516

@@ -71,3 +72,81 @@ checkbox:
7172

7273
`mdc-form-field` is dark theme aware, and will change the text color to the "primary on dark" text
7374
color when used within a dark theme.
75+
76+
77+
## JS Usage
78+
79+
### Including in code
80+
81+
#### ES2015
82+
83+
```javascript
84+
import {MDCFormField, MDCFormFieldFoundation} from 'mdc-form-field';
85+
```
86+
87+
#### CommonJS
88+
89+
```javascript
90+
const mdcFormField = require('mdc-form-field');
91+
const MDCFormField = mdcFormField.MDCFormField;
92+
const MDCFormFieldFoundation = mdcFormField.MDCFormFieldFoundation;
93+
```
94+
95+
#### AMD
96+
97+
```javascript
98+
require(['path/to/mdc-form-field'], mdcFormField => {
99+
const MDCFormField = mdcFormField.MDCFormField;
100+
const MDCFormFieldFoundation = mdcFormField.MDCFormFieldFoundation;
101+
});
102+
```
103+
104+
#### Global
105+
106+
```javascript
107+
const MDCFormField = mdc.radio.MDCFormField;
108+
const MDCFormFieldFoundation = mdc.radio.MDCFormFieldFoundation;
109+
```
110+
111+
### Instantiation
112+
113+
```javascript
114+
import {MDCFormField} from 'mdc-form-field';
115+
116+
const formField = new MDCFormField(document.querySelector('.mdc-form-field'));
117+
```
118+
119+
### MDCFormField API
120+
121+
The `MDCFormField` functionality is exposed through a single accessor method.
122+
123+
#### MDCFormField.input
124+
125+
Read-write property that works with an instance of an MDC-Web input element.
126+
127+
In order for the label ripple integration to work correctly, this property needs to be set to a
128+
valid instance of an MDC-Web input element which exposes a `ripple` getter.
129+
130+
```javascript
131+
const formField = new MDCFormField(document.querySelector('.mdc-form-field'));
132+
const radio = new MDCRadio(document.querySelector('.mdc-radio'));
133+
134+
formField.input = radio;
135+
```
136+
137+
No action is taken if the `input` property is not set or the input instance doesn't expose a
138+
`ripple` getter.
139+
140+
141+
### Adapter
142+
143+
The adapter for `MDCFormField` is extremely simple, providing only methods for adding and
144+
removing event listeners from the label, as well as methods for activating and deactivating
145+
the input ripple.
146+
147+
| Method Signature | Description |
148+
| --- | --- |
149+
| `registerInteractionHandler(type: string, handler: EventListener) => void` | Adds an event listener `handler` for event type `type` to the label. |
150+
| `deregisterInteractionHandler(type: string, handler: EventListener) => void` | Removes an event listener `handler` for event type `type` to the label. |
151+
| `activateInputRipple() => void` | Activates the ripple on the input element. Should call `activate` on the input element's `ripple` property. |
152+
| `deactivateInputRipple() => void` | Deactivates the ripple on the input element. Should call `deactivate` on the input element's `ripple` property. |

packages/mdc-form-field/constants.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright 2017 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
export const cssClasses = {
18+
ROOT: 'mdc-form-field',
19+
};
20+
21+
export const strings = {
22+
LABEL_SELECTOR: '.mdc-form-field > label',
23+
};

packages/mdc-form-field/foundation.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Copyright 2017 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {MDCFoundation} from '@material/base';
18+
import {cssClasses, strings} from './constants';
19+
20+
export default class MDCFormFieldFoundation extends MDCFoundation {
21+
static get cssClasses() {
22+
return cssClasses;
23+
}
24+
25+
static get strings() {
26+
return strings;
27+
}
28+
29+
static get defaultAdapter() {
30+
return {
31+
registerInteractionHandler: (/* type: string, handler: EventListener */) => {},
32+
deregisterInteractionHandler: (/* type: string, handler: EventListener */) => {},
33+
activateInputRipple: () => {},
34+
deactivateInputRipple: () => {},
35+
};
36+
}
37+
38+
constructor(adapter) {
39+
super(Object.assign(MDCFormFieldFoundation.defaultAdapter, adapter));
40+
this.clickHandler_ = (evt) => this.handleClick_(evt);
41+
}
42+
43+
init() {
44+
this.adapter_.registerInteractionHandler('click', this.clickHandler_);
45+
}
46+
47+
destroy() {
48+
this.adapter_.deregisterInteractionHandler('click', this.clickHandler_);
49+
}
50+
51+
handleClick_(evt) {
52+
this.adapter_.activateInputRipple();
53+
requestAnimationFrame(() => this.adapter_.deactivateInputRipple());
54+
}
55+
}

packages/mdc-form-field/index.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Copyright 2017 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {MDCComponent} from '@material/base';
18+
import MDCFormFieldFoundation from './foundation';
19+
20+
export {MDCFormFieldFoundation};
21+
22+
export class MDCFormField extends MDCComponent {
23+
static attachTo(root) {
24+
return new MDCFormField(root);
25+
}
26+
27+
set input(input) {
28+
this.input_ = input;
29+
}
30+
31+
get input() {
32+
return this.input_;
33+
}
34+
35+
get label_() {
36+
return this.root_.querySelector(MDCFormFieldFoundation.strings.LABEL_SELECTOR);
37+
}
38+
39+
getDefaultFoundation() {
40+
return new MDCFormFieldFoundation({
41+
registerInteractionHandler: (type, handler) => this.label_.addEventListener(type, handler),
42+
deregisterInteractionHandler: (type, handler) => this.label_.removeEventListener(type, handler),
43+
activateInputRipple: () => {
44+
if (this.input_ && this.input_.ripple) {
45+
this.input_.ripple.activate();
46+
}
47+
},
48+
deactivateInputRipple: () => {
49+
if (this.input_ && this.input_.ripple) {
50+
this.input_.ripple.deactivate();
51+
}
52+
},
53+
});
54+
}
55+
}

packages/mdc-form-field/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
{
22
"name": "@material/form-field",
3-
"description": "Material Components for the web wrapper styles for laying out form fields and labels next to one another",
3+
"description": "Material Components for the web wrapper for laying out form fields and labels next to one another",
44
"version": "0.1.1",
55
"license": "Apache-2.0",
66
"keywords": [
77
"material components",
88
"material design",
99
"form"
1010
],
11+
"main": "index.js",
1112
"repository": {
1213
"type": "git",
1314
"url": "https://github.com/material-components/material-components-web.git"
1415
},
1516
"dependencies": {
17+
"@material/base": "^0.1.1",
1618
"@material/rtl": "^0.1.1",
1719
"@material/theme": "^0.1.1",
1820
"@material/typography": "^0.1.1"

packages/mdc-radio/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ export class MDCRadio extends MDCComponent {
4242
this.foundation_.setDisabled(disabled);
4343
}
4444

45+
get ripple() {
46+
return this.ripple_;
47+
}
48+
4549
constructor(...args) {
4650
super(...args);
4751
this.ripple_ = this.initRipple_();

0 commit comments

Comments
 (0)