Convert uncontrolled Field usages to controlled

As part of adding validation to Field, the logic is simpler to follow if we can
assume that all usages of Field use it as a controlled component, instead of
supporting both controlled and uncontrolled.

This converts the uncontrolled usages to controlled.
This commit is contained in:
J. Ryan Stinnett 2019-03-12 16:17:21 +00:00
parent cff3c94858
commit d4dbba3938
5 changed files with 108 additions and 31 deletions

View file

@ -32,6 +32,7 @@ import sessionStore from '../../../stores/SessionStore';
module.exports = React.createClass({
displayName: 'ChangePassword',
propTypes: {
onFinished: PropTypes.func,
onError: PropTypes.func,
@ -73,6 +74,9 @@ module.exports = React.createClass({
return {
phase: this.Phases.Edit,
cachedPassword: null,
oldPassword: "",
newPassword: "",
newPasswordConfirm: "",
};
},
@ -165,6 +169,9 @@ module.exports = React.createClass({
}).finally(() => {
this.setState({
phase: this.Phases.Edit,
oldPassword: "",
newPassword: "",
newPasswordConfirm: "",
});
}).done();
},
@ -192,11 +199,29 @@ module.exports = React.createClass({
);
},
onChangeOldPassword(ev) {
this.setState({
oldPassword: ev.target.value,
});
},
onChangeNewPassword(ev) {
this.setState({
newPassword: ev.target.value,
});
},
onChangeNewPasswordConfirm(ev) {
this.setState({
newPasswordConfirm: ev.target.value,
});
},
onClickChange: function(ev) {
ev.preventDefault();
const oldPassword = this.state.cachedPassword || this.refs.old_input.value;
const newPassword = this.refs.new_input.value;
const confirmPassword = this.refs.confirm_input.value;
const oldPassword = this.state.cachedPassword || this.state.oldPassword;
const newPassword = this.state.newPassword;
const confirmPassword = this.state.newPasswordConfirm;
const err = this.props.onCheckPassword(
oldPassword, newPassword, confirmPassword,
);
@ -217,7 +242,12 @@ module.exports = React.createClass({
if (!this.state.cachedPassword) {
currentPassword = (
<div className={rowClassName}>
<Field id="passwordold" type="password" ref="old_input" label={_t('Current password')} />
<Field id="mx_ChangePassword_oldPassword"
type="password"
label={_t('Current password')}
value={this.state.oldPassword}
onChange={this.onChangeOldPassword}
/>
</div>
);
}
@ -230,11 +260,21 @@ module.exports = React.createClass({
<form className={this.props.className} onSubmit={this.onClickChange}>
{ currentPassword }
<div className={rowClassName}>
<Field id="password1" type="password" ref="new_input" label={passwordLabel}
autoFocus={this.props.autoFocusNewPasswordInput} />
<Field id="mx_ChangePassword_newPassword"
type="password"
label={passwordLabel}
value={this.state.newPassword}
autoFocus={this.props.autoFocusNewPasswordInput}
onChange={this.onChangeNewPassword}
/>
</div>
<div className={rowClassName}>
<Field id="password2" type="password" ref="confirm_input" label={_t("Confirm password")} />
<Field id="mx_ChangePassword_newPasswordConfirm"
type="password"
label={_t("Confirm password")}
value={this.state.newPasswordConfirm}
onChange={this.onChangeNewPasswordConfirm}
/>
</div>
<AccessibleButton className={buttonClassName} kind={this.props.buttonKind} onClick={this.onClickChange}>
{ _t('Change Password') }

View file

@ -119,6 +119,7 @@ export default class EmailAddresses extends React.Component {
verifying: false,
addTask: null,
continueDisabled: false,
newEmailAddress: "",
};
}
@ -134,14 +135,20 @@ export default class EmailAddresses extends React.Component {
this.setState({emails: this.state.emails.filter((e) => e !== address)});
};
_onChangeNewEmailAddress = (e) => {
this.setState({
newEmailAddress: e.target.value,
});
};
_onAddClick = (e) => {
e.stopPropagation();
e.preventDefault();
if (!this.refs.newEmailAddress) return;
if (!this.state.newEmailAddress) return;
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const email = this.refs.newEmailAddress.value;
const email = this.state.newEmailAddress;
// TODO: Inline field validation
if (!Email.looksValid(email)) {
@ -173,14 +180,14 @@ export default class EmailAddresses extends React.Component {
this.setState({continueDisabled: true});
this.state.addTask.checkEmailLinkClicked().then(() => {
const email = this.refs.newEmailAddress.value;
const email = this.state.newEmailAddress;
this.setState({
emails: [...this.state.emails, {address: email, medium: "email"}],
addTask: null,
continueDisabled: false,
verifying: false,
newEmailAddress: "",
});
this.refs.newEmailAddress.value = "";
}).catch((err) => {
this.setState({continueDisabled: false});
if (err.errcode !== 'M_THREEPID_AUTH_FAILED') {
@ -221,8 +228,14 @@ export default class EmailAddresses extends React.Component {
{existingEmailElements}
<form onSubmit={this._onAddClick} autoComplete={false}
noValidate={true} className="mx_EmailAddresses_new">
<Field id="newEmailAddress" ref="newEmailAddress" label={_t("Email Address")}
type="text" autoComplete="off" disabled={this.state.verifying} />
<Field id="mx_EmailAddressses_newEmailAddress"
type="text"
label={_t("Email Address")}
autoComplete="off"
disabled={this.state.verifying}
value={this.state.newEmailAddress}
onChange={this._onChangeNewEmailAddress}
/>
{addButton}
</form>
</div>

View file

@ -117,6 +117,8 @@ export default class PhoneNumbers extends React.Component {
addTask: null,
continueDisabled: false,
phoneCountry: "",
newPhoneNumber: "",
newPhoneNumberCode: "",
};
}
@ -132,14 +134,26 @@ export default class PhoneNumbers extends React.Component {
this.setState({msisdns: this.state.msisdns.filter((e) => e !== address)});
};
_onChangeNewPhoneNumber = (e) => {
this.setState({
newPhoneNumber: e.target.value,
});
};
_onChangeNewPhoneNumberCode = (e) => {
this.setState({
newPhoneNumberCode: e.target.value,
});
};
_onAddClick = (e) => {
e.stopPropagation();
e.preventDefault();
if (!this.refs.newPhoneNumber) return;
if (!this.state.newPhoneNumber) return;
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const phoneNumber = this.refs.newPhoneNumber.value;
const phoneNumber = this.state.newPhoneNumber;
const phoneCountry = this.state.phoneCountry;
const task = new AddThreepid();
@ -162,7 +176,7 @@ export default class PhoneNumbers extends React.Component {
e.preventDefault();
this.setState({continueDisabled: true});
const token = this.refs.newPhoneNumberCode.value;
const token = this.state.newPhoneNumberCode;
this.state.addTask.haveMsisdnToken(token).then(() => {
this.setState({
msisdns: [...this.state.msisdns, {address: this.state.verifyMsisdn, medium: "msisdn"}],
@ -171,8 +185,9 @@ export default class PhoneNumbers extends React.Component {
verifying: false,
verifyMsisdn: "",
verifyError: null,
newPhoneNumber: "",
newPhoneNumberCode: "",
});
this.refs.newPhoneNumber.value = "";
}).catch((err) => {
this.setState({continueDisabled: false});
if (err.errcode !== 'M_THREEPID_AUTH_FAILED') {
@ -213,8 +228,14 @@ export default class PhoneNumbers extends React.Component {
{this.state.verifyError}
</div>
<form onSubmit={this._onContinueClick} autoComplete={false} noValidate={true}>
<Field id="newPhoneNumberCode" ref="newPhoneNumberCode" label={_t("Verification code")}
type="text" autoComplete="off" disabled={this.state.continueDisabled} />
<Field id="mx_PhoneNumbers_newPhoneNumberCode"
type="text"
label={_t("Verification code")}
autoComplete="off"
disabled={this.state.continueDisabled}
value={this.state.newPhoneNumberCode}
onChange={this._onChangeNewPhoneNumberCode}
/>
<AccessibleButton onClick={this._onContinueClick} kind="primary"
disabled={this.state.continueDisabled}>
{_t("Continue")}
@ -238,9 +259,15 @@ export default class PhoneNumbers extends React.Component {
<form onSubmit={this._onAddClick} autoComplete={false}
noValidate={true} className="mx_PhoneNumbers_new">
<div className="mx_PhoneNumbers_input">
<Field id="newPhoneNumber" ref="newPhoneNumber" label={_t("Phone Number")}
type="text" autoComplete="off" disabled={this.state.verifying}
prefix={phoneCountry} />
<Field id="mx_PhoneNumbers_newPhoneNumber"
type="text"
label={_t("Phone Number")}
autoComplete="off"
disabled={this.state.verifying}
prefix={phoneCountry}
value={this.state.newPhoneNumber}
onChange={this._onChangeNewPhoneNumber}
/>
</div>
{addVerifySection}
</form>