mirror of
https://github.com/material-components/material-web.git
synced 2024-09-21 18:50:12 +03:00
Merge pull request #373 from material-components/radio-checked-bug
Fix broken checked property in <mwc-radio>
This commit is contained in:
commit
40f5e43947
@ -26,6 +26,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- Improve README for `<mwc-button>`
|
||||
- Improve README for `<mwc-icon-button>`
|
||||
- Split toggling icon button out into `@material/mwc-icon-button-toggle` with tag name `<mwc-icon-button-toggle>`
|
||||
- Fix bug where setting the `checked` property on an `<mwc-radio>` did not
|
||||
result in the other radios in the group becoming unchecked.
|
||||
|
||||
## [0.6.0] - 2019-06-05
|
||||
- Upgrade lerna to 3.x
|
||||
|
@ -24,11 +24,46 @@ export class RadioBase extends FormElement {
|
||||
|
||||
@query('input') protected formElement!: HTMLInputElement;
|
||||
|
||||
@property({type: Boolean})
|
||||
@observer(function(this: RadioBase, checked: boolean) {
|
||||
this.formElement.checked = checked;
|
||||
})
|
||||
checked = false;
|
||||
private _checked = false;
|
||||
|
||||
@property({type: Boolean, reflect: true})
|
||||
get checked() {
|
||||
return this._checked;
|
||||
}
|
||||
|
||||
/**
|
||||
* We define our own getter/setter for `checked` because we need to track
|
||||
* changes to it synchronously.
|
||||
*
|
||||
* The order in which the `checked` property is set across radio buttons
|
||||
* within the same group is very important. However, we can't rely on
|
||||
* UpdatingElement's `updated` callback to observe these changes (which is
|
||||
* also what the `@observer` decorator uses), because it batches changes to
|
||||
* all properties.
|
||||
*
|
||||
* Consider:
|
||||
*
|
||||
* radio1.disabled = true;
|
||||
* radio2.checked = true;
|
||||
* radio1.checked = true;
|
||||
*
|
||||
* In this case we'd first see all changes for radio1, and then for radio2,
|
||||
* and we couldn't tell that radio1 was the most recently checked.
|
||||
*/
|
||||
set checked(checked: boolean) {
|
||||
const oldValue = this._checked;
|
||||
if (!!checked === !!oldValue) {
|
||||
return;
|
||||
}
|
||||
this._checked = checked;
|
||||
if (this.formElement) {
|
||||
this.formElement.checked = checked;
|
||||
}
|
||||
if (this._selectionController) {
|
||||
this._selectionController.update(this);
|
||||
}
|
||||
this.requestUpdate('checked', oldValue);
|
||||
}
|
||||
|
||||
@property({type: Boolean})
|
||||
@observer(function(this: RadioBase, disabled: boolean) {
|
||||
@ -127,6 +162,9 @@ export class RadioBase extends FormElement {
|
||||
|
||||
firstUpdated() {
|
||||
super.firstUpdated();
|
||||
// We might not have been able to synchronize this from the checked setter
|
||||
// earlier, if checked was set before the input was stamped.
|
||||
this.formElement.checked = this.checked;
|
||||
if (this._selectionController) {
|
||||
this._selectionController.update(this);
|
||||
}
|
||||
|
@ -14,22 +14,65 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {assert} from 'chai';
|
||||
import {Radio} from '@material/mwc-radio';
|
||||
import {assert} from 'chai';
|
||||
import {html, render} from 'lit-html';
|
||||
|
||||
let element;
|
||||
let container;
|
||||
|
||||
suite('mwc-radio');
|
||||
|
||||
beforeEach(() => {
|
||||
element = document.createElement('mwc-radio');
|
||||
document.body.appendChild(element);
|
||||
before(() => {
|
||||
container = document.createElement('main');
|
||||
document.body.appendChild(container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(element);
|
||||
render(html``, container);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
|
||||
test('initializes as an mwc-radio', () => {
|
||||
assert.instanceOf(element, Radio);
|
||||
const radio = document.createElement('mwc-radio');
|
||||
container.appendChild(radio);
|
||||
assert.instanceOf(radio, Radio);
|
||||
});
|
||||
|
||||
test('radio group', async () => {
|
||||
render(
|
||||
html`
|
||||
<mwc-radio name="a"></mwc-group>
|
||||
<mwc-radio name="a"></mwc-group>
|
||||
<mwc-radio name="b"></mwc-group>
|
||||
`,
|
||||
container);
|
||||
|
||||
const [a1, a2, b1] = [...container.querySelectorAll('mwc-radio')];
|
||||
assert.isFalse(a1.checked);
|
||||
assert.isFalse(a2.checked);
|
||||
assert.isFalse(b1.checked);
|
||||
|
||||
a1.checked = true;
|
||||
assert.isTrue(a1.checked);
|
||||
assert.isFalse(a2.checked);
|
||||
assert.isFalse(b1.checked);
|
||||
|
||||
a2.checked = true;
|
||||
assert.isFalse(a1.checked);
|
||||
assert.isTrue(a2.checked);
|
||||
assert.isFalse(b1.checked);
|
||||
|
||||
b1.checked = true;
|
||||
assert.isFalse(a1.checked);
|
||||
assert.isTrue(a2.checked);
|
||||
assert.isTrue(b1.checked);
|
||||
|
||||
a2.checked = false;
|
||||
b1.checked = false;
|
||||
assert.isFalse(a1.checked);
|
||||
assert.isFalse(a2.checked);
|
||||
assert.isFalse(b1.checked);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user