Skip to content

Commit da4393c

Browse files
Gut internal intermediate state from checkbox
1 parent a665957 commit da4393c

File tree

3 files changed

+56
-152
lines changed

3 files changed

+56
-152
lines changed

RELEASENOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ _Salesforce Lightning Design System :: React Components :: design-system-react_
55

66
These are changes that have backwards-compatible solutions present and that compatibiity will be removed at a breaking change release in the future.
77

8+
- `Checkbox`'s `onChange` now recieves `event, {checked: [boolean], indeterminate: [boolean] }`. Previously, `checked` was the first parameter.
89
- `TabsPane` has be replaced with `TabsPanel`.
910
- `Input`'s props: `iconPosition`, `iconAssistiveText`, `iconCategory`, `iconName`, `onIconClick` are deprecated. An `Icon` component should be used instead.
1011
- `DataTable`'s' `collection`, `onSelect`, `onDeselect` are deprecated.

components/forms/checkbox/index.jsx

Lines changed: 25 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const Checkbox = React.createClass({
5151
*/
5252
assistiveText: React.PropTypes.string,
5353
/**
54-
* The Checkbox is a controlled component, and will always be in this state.
54+
* The Checkbox is a controlled component, and will always be in this state. If checked is not defined, the state of the uncontrolled native `input` component will be used.
5555
*/
5656
checked: React.PropTypes.bool,
5757
/**
@@ -75,7 +75,7 @@ const Checkbox = React.createClass({
7575
*/
7676
id: PropTypes.string,
7777
/**
78-
* The Checkbox will be indeterminate if its state can not be figured out.
78+
* The Checkbox will be indeterminate if its state can not be figured out or is partially checked. Once a checkbox is indeterminate, a click should cause it to be checked. Since a user cannot put a checkbox into an indeterminate state, it is assumed you are controlling the value of `checked` with the parent, also, and that this is a controlled component.
7979
*/
8080
indeterminate: React.PropTypes.bool,
8181
/**
@@ -96,94 +96,10 @@ const Checkbox = React.createClass({
9696
required: PropTypes.bool
9797
},
9898

99-
getDefaultProps () {
100-
return {
101-
id: shortid.generate(),
102-
checked: null,
103-
indeterminate: false
104-
};
99+
componentWillMount () {
100+
this.generatedId = shortid.generate();
105101
},
106102

107-
getInitialState () {
108-
return {
109-
checked: this.props.indeterminate === true ? false : this.props.checked,
110-
defaultChecked: this.props.checked,
111-
indeterminate: this.props.indeterminate === true ? true : null
112-
};
113-
},
114-
115-
componentDidMount () {
116-
const checkbox = this.input;
117-
checkbox.checked = this.state.indeterminate === true ? false : this.state.defaultChecked;
118-
checkbox.indeterminate = this.state.indeterminate;
119-
},
120-
121-
122-
componentWillReceiveProps (nextProps) {
123-
const checkbox = this.input;
124-
checkbox.checked = nextProps.indeterminate === true ? false : nextProps.checked;
125-
checkbox.indeterminate = nextProps.indeterminate;
126-
this.setState({
127-
checked: nextProps.indeterminate === true ? false : nextProps.checked,
128-
indeterminate: nextProps.indeterminate
129-
});
130-
},
131-
132-
shouldComponentUpdate (nextProps, nextState) {
133-
let toReturn = true;
134-
let toReturnIndeterminate = true;
135-
let toReturnChecked = true;
136-
137-
if (
138-
nextProps.indeterminate === this.props.indeterminate
139-
&& nextProps.indeterminate === nextState.indeterminate
140-
&& nextProps.indeterminate === this.state.indeterminate
141-
) {
142-
toReturnIndeterminate = false;
143-
}
144-
145-
// Sometimes the indeterminate stuff is not a boolean, so double-check ehre
146-
if (
147-
(typeof nextProps.indeterminate === 'object' && nextProps.indeterminate === null)
148-
&& (typeof this.props.indeterminate === 'object' && this.props.indeterminate === null)
149-
&& (this.state.indeterminate === false)
150-
&& (nextState.indeterminate === false)
151-
) {
152-
toReturnIndeterminate = false;
153-
}
154-
155-
if (
156-
nextProps.checked === this.props.checked
157-
&& nextProps.checked === nextState.checked
158-
&& nextProps.checked === this.state.checked
159-
) {
160-
toReturnChecked = false;
161-
}
162-
163-
toReturn = toReturnIndeterminate === true || toReturnChecked === true;
164-
return toReturn;
165-
},
166-
167-
componentWillUpdate (nextProps, nextState) {
168-
if (nextProps.indeterminate === true) {
169-
nextState.checked = null;
170-
}
171-
if (nextProps.checked !== nextState.checked) {
172-
173-
}
174-
},
175-
176-
componentDidUpdate () {
177-
const checkbox = this.input;
178-
checkbox.checked = this.state.indeterminate === true ? null : this.state.checked === true ? true : null;
179-
checkbox.indeterminate = this.state.indeterminate;
180-
if (this.state.indeterminate === false && this.state.checked === false) {
181-
checkbox.checked = false;
182-
}
183-
},
184-
185-
186-
187103
// ### Render
188104
render () {
189105
const {
@@ -218,16 +134,21 @@ const Checkbox = React.createClass({
218134
{required ? <abbr className="slds-required" title="required">*</abbr> : null}
219135
<input
220136
{...props}
221-
id={id}
222-
checked={indeterminate === true ? null : checked}
223-
indeterminate={indeterminate}
137+
id={id || this.generatedId}
138+
checked={checked}
224139
name={name}
225140
disabled={disabled}
226141
onChange={this.handleChange}
227142
type="checkbox"
228-
ref={(component) => this.input = component}
143+
ref={
144+
(component) => {
145+
if (component) {
146+
component.indeterminate = indeterminate;
147+
}
148+
this.input = component;
149+
}}
229150
/>
230-
<label className="slds-checkbox__label" htmlFor={id}>
151+
<label className="slds-checkbox__label" htmlFor={id || this.generatedId}>
231152
<span className="slds-checkbox--faux"></span>
232153
{label
233154
? <span className="slds-form-element__label">
@@ -247,47 +168,19 @@ const Checkbox = React.createClass({
247168
);
248169
},
249170

250-
getValue () {
251-
const checkbox = this.input;
252-
return !checkbox.checked;
253-
},
254-
255-
isChecked () {
256-
return this.getValue() || false;
257-
},
258-
259171
handleChange (event) {
260-
let value = event.target.checked;
261-
const props = this.props;
262-
const oldValue = this.getValue();
263-
264-
if (props.indeterminate === true) {
265-
if (typeof props.nextValue === 'function') {
266-
value = props.nextValue(oldValue, this.props);
267-
}
268-
}
172+
const value = event.target.checked;
173+
const {
174+
checked,
175+
indeterminate,
176+
onChange
177+
} = this.props;
269178

270-
if (oldValue !== !this.state.defaultValue) {
271-
if (isFunction(props.onChange)) {
272-
this.props.onChange(value, event, {
273-
checked: value,
274-
indeterminate: null
275-
});
276-
}
277-
this.setState({
278-
checked: value,
279-
indeterminate: null
280-
});
281-
} else {
282-
if (isFunction(props.onChange)) {
283-
this.props.onChange(value, event, {
284-
checked: props.indeterminate === true ? null : value,
285-
indeterminate: props.indeterminate
286-
});
287-
}
288-
this.setState({
289-
checked: props.indeterminate === true ? null : value,
290-
indeterminate: props.indeterminate
179+
if (isFunction(onChange)) {
180+
// `checked` is present twice to maintain backwards compatibility. Please remove first parameter `value` on the next breaking change.
181+
onChange(value, event, {
182+
checked: indeterminate ? true : !checked,
183+
indeterminate: false
291184
});
292185
}
293186
},

stories/forms/checkbox/index.jsx

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,39 @@ const CheckboxIndeterminate = React.createClass({
1212
return {
1313
indeterminate: true,
1414
checked: true,
15-
currentStateHelper: 'Default'
15+
currentStateHelper: 'Indeterminate'
1616
};
1717
},
1818

1919
handleChange (checked, event, data) {
20-
action('handleChange')(checked, event, `checked: ${data.checked}, indeterminate: ${data.indeterminate}`);
20+
const checkedLabel = data.checked ? 'Checked' : 'Unchecked';
2121
this.setState({
22-
currentStateHelper: data.indeterminate === true ? 'Inderterminate' : data.checked === true ? 'Checked' : 'Unchecked',
23-
checked: data.indeterminate === true ? null : data.checked,
22+
checked: data.checked,
23+
currentStateHelper: data.indeterminate ? 'Indeterminate' : checkedLabel,
2424
indeterminate: data.indeterminate
2525
});
26+
27+
action('handleChange')(
28+
checked,
29+
event,
30+
`checked: ${data.checked},
31+
indeterminate: ${data.indeterminate}`
32+
);
2633
},
2734

2835
changeToIndeterminate () {
29-
this.setState({ currentStateHelper: 'Inderterminate', indeterminate: true, checked: null });
30-
action('changeToIndeterminate')(event, `checked: null, indeterminate: true`);
36+
this.setState({ currentStateHelper: 'Inderterminate', checked: true, indeterminate: true });
37+
action('changeToIndeterminate')(event, 'checked: true, indeterminate: true');
3138
},
3239

3340
changeToCheck () {
34-
this.setState({ currentStateHelper: 'Checked', checked: true, indeterminate: null });
35-
action('changeToCheck')(event, `checked: true, indeterminate: null`);
41+
this.setState({ currentStateHelper: 'Checked', checked: true, indeterminate: false });
42+
action('changeToCheck')(event, 'checked: true, indeterminate: false');
3643
},
3744

3845
changeToUnChecked () {
39-
this.setState({ currentStateHelper: 'Unchecked', checked: false, indeterminate: null });
40-
action('changeToUnChecked')(event, `checked: false, indeterminate: null`);
46+
this.setState({ currentStateHelper: 'Unchecked', checked: false, indeterminate: false });
47+
action('changeToUnChecked')(event, 'checked: false, indeterminate: false');
4148
},
4249

4350
render () {
@@ -81,6 +88,7 @@ storiesOf(FORMS_CHECKBOX, module)
8188
assistiveText="Checkbox"
8289
label="Checkbox Label"
8390
name="checkbox-example-standard"
91+
onChange={action('change')}
8492
/>
8593
))
8694
.add('Checkbox (indeterminate)', () => (
@@ -91,23 +99,24 @@ storiesOf(FORMS_CHECKBOX, module)
9199
assistiveText="Checkbox (required)"
92100
label="Checkbox Label"
93101
name="checkbox-example-standard-required"
102+
onChange={action('change')}
94103
required
95104
/>
96105
))
97106
.add('Checkbox (assistive text)', () => (
98107
<div>
99108
<Checkbox
100-
assistiveText="Checkbox (assistiveText)"
109+
assistiveText={`This is my checkbox.
110+
There are many like it, but this one is mine.
111+
My checkbox is my best friend.
112+
It is my life.
113+
I must master it as I must master my life.
114+
Without me, my checkbox is useless. Without my checkbox, I am useless.
115+
I must make my checkbox true.
116+
I must make it truer than my radio button who is trying to... `}
101117
label="Checkbox Label"
102118
name="checkbox-example-standard-assistiveText"
103-
assistiveText={`This is my checkbox.
104-
There are many like it, but this one is mine.
105-
My checkbox is my best friend.
106-
It is my life.
107-
I must master it as I must master my life.
108-
Without me, my checkbox is useless. Without my checkbox, I am useless.
109-
I must make my checkbox true.
110-
I must make it truer than my radio button who is trying to... `}
119+
onChange={action('change')}
111120
/>
112121
<div className="slds-box slds-text-longform slds-m-top--large">
113122
<p>
@@ -127,9 +136,10 @@ storiesOf(FORMS_CHECKBOX, module)
127136
.add('Checkbox (checked)', () => (
128137
<Checkbox
129138
assistiveText="Checkbox (checked)"
139+
checked
130140
label="Checkbox Label"
131141
name="checkbox-example-standard-checked"
132-
checked
142+
onChange={action('change')}
133143
/>
134144
))
135145
;

0 commit comments

Comments
 (0)