Focus the first invalid field

This adjusts the submission step to focus the first invalid field and redisplay
validation. This also rearranges the older style field error handling on
registration which is slated for removal once we convert all fields to the new
style.
This commit is contained in:
J. Ryan Stinnett 2019-04-17 14:23:59 +01:00
parent 62a01e7a37
commit 5d95c31875
2 changed files with 60 additions and 21 deletions

View file

@ -89,34 +89,37 @@ module.exports = React.createClass({
// is the one from the first invalid field. // is the one from the first invalid field.
// It's not super ideal that this just calls // It's not super ideal that this just calls
// onValidationChange once for each invalid field. // onValidationChange once for each invalid field.
// TODO: Change this to trigger new-style validation for an invalid fields. // TODO: Remove these calls once converted to new-style validation.
this.validateField(FIELD_PHONE_NUMBER, ev.type); this.validateField(FIELD_PHONE_NUMBER, ev.type);
this.validateField(FIELD_EMAIL, ev.type); this.validateField(FIELD_EMAIL, ev.type);
this.validateField(FIELD_PASSWORD_CONFIRM, ev.type); this.validateField(FIELD_PASSWORD_CONFIRM, ev.type);
this.validateField(FIELD_PASSWORD, ev.type); this.validateField(FIELD_PASSWORD, ev.type);
this.validateField(FIELD_USERNAME, ev.type); this.validateField(FIELD_USERNAME, ev.type);
const allFieldsValid = this.verifyFieldsBeforeSubmit();
if (!allFieldsValid) {
return;
}
const self = this; const self = this;
if (this.allFieldsValid()) { if (this.state.email == '') {
if (this.state.email == '') { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); Modal.createTrackedDialog('If you don\'t specify an email address...', '', QuestionDialog, {
Modal.createTrackedDialog('If you don\'t specify an email address...', '', QuestionDialog, { title: _t("Warning!"),
title: _t("Warning!"), description:
description: <div>
<div> { _t("If you don't specify an email address, you won't be able to reset your password. " +
{ _t("If you don't specify an email address, you won't be able to reset your password. " + "Are you sure?") }
"Are you sure?") } </div>,
</div>, button: _t("Continue"),
button: _t("Continue"), onFinished: function(confirmed) {
onFinished: function(confirmed) { if (confirmed) {
if (confirmed) { self._doSubmit(ev);
self._doSubmit(ev); }
} },
}, });
}); } else {
} else { self._doSubmit(ev);
self._doSubmit(ev);
}
} }
}, },
@ -138,6 +141,27 @@ module.exports = React.createClass({
} }
}, },
verifyFieldsBeforeSubmit() {
if (this.allFieldsValid()) {
return true;
}
const invalidField = this.findFirstInvalidField([
FIELD_USERNAME,
FIELD_PASSWORD,
FIELD_PASSWORD_CONFIRM,
FIELD_EMAIL,
FIELD_PHONE_NUMBER,
]);
if (!invalidField) {
return true;
}
invalidField.focus();
return false;
},
/** /**
* @returns {boolean} true if all fields were valid last time they were validated. * @returns {boolean} true if all fields were valid last time they were validated.
*/ */
@ -158,6 +182,15 @@ module.exports = React.createClass({
return true; return true;
}, },
findFirstInvalidField(fieldIDs) {
for (const fieldID of fieldIDs) {
if (!this.state.fieldValid[fieldID] && this[fieldID]) {
return this[fieldID];
}
}
return null;
},
validateField: function(fieldID, eventType) { validateField: function(fieldID, eventType) {
const pwd1 = this.state.password.trim(); const pwd1 = this.state.password.trim();
const pwd2 = this.state.passwordConfirm.trim(); const pwd2 = this.state.passwordConfirm.trim();
@ -362,6 +395,7 @@ module.exports = React.createClass({
return <Field return <Field
className={this._classForField(FIELD_USERNAME)} className={this._classForField(FIELD_USERNAME)}
id="mx_RegistrationForm_username" id="mx_RegistrationForm_username"
ref={field => this[FIELD_USERNAME] = field}
type="text" type="text"
autoFocus={true} autoFocus={true}
label={_t("Username")} label={_t("Username")}

View file

@ -86,6 +86,10 @@ export default class Field extends React.PureComponent {
} }
}; };
focus() {
this.input.focus();
}
validate({ value, focused }) { validate({ value, focused }) {
if (!this.props.onValidate) { if (!this.props.onValidate) {
return; return;
@ -107,6 +111,7 @@ export default class Field extends React.PureComponent {
// Set some defaults for the <input> element // Set some defaults for the <input> element
inputProps.type = inputProps.type || "text"; inputProps.type = inputProps.type || "text";
inputProps.ref = input => this.input = input;
inputProps.placeholder = inputProps.placeholder || inputProps.label; inputProps.placeholder = inputProps.placeholder || inputProps.label;
inputProps.onFocus = this.onFocus; inputProps.onFocus = this.onFocus;