diff --git a/res/css/_components.scss b/res/css/_components.scss
index 1f896d270d..8bea138acb 100644
--- a/res/css/_components.scss
+++ b/res/css/_components.scss
@@ -100,6 +100,7 @@
@import "./views/elements/_ToggleSwitch.scss";
@import "./views/elements/_ToolTipButton.scss";
@import "./views/elements/_Tooltip.scss";
+@import "./views/elements/_Validation.scss";
@import "./views/globals/_MatrixToolbar.scss";
@import "./views/groups/_GroupPublicityToggle.scss";
@import "./views/groups/_GroupRoomList.scss";
diff --git a/res/css/views/elements/_Validation.scss b/res/css/views/elements/_Validation.scss
new file mode 100644
index 0000000000..08ae793663
--- /dev/null
+++ b/res/css/views/elements/_Validation.scss
@@ -0,0 +1,32 @@
+/*
+Copyright 2019 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_Validation_details {
+ padding-left: 15px;
+}
+
+.mx_Validation_detail {
+ font-weight: normal;
+
+ // TODO: Check / cross images
+ &.mx_Validation_valid {
+ color: $input-valid-border-color;
+ }
+
+ &.mx_Validation_invalid {
+ color: $input-invalid-border-color;
+ }
+}
diff --git a/src/components/views/auth/RegistrationForm.js b/src/components/views/auth/RegistrationForm.js
index 1784ab61c3..83ea4dfae6 100644
--- a/src/components/views/auth/RegistrationForm.js
+++ b/src/components/views/auth/RegistrationForm.js
@@ -25,6 +25,7 @@ import Modal from '../../../Modal';
import { _t } from '../../../languageHandler';
import SdkConfig from '../../../SdkConfig';
import { SAFE_LOCALPART_REGEX } from '../../../Registration';
+import withValidation from '../elements/Validation';
const FIELD_EMAIL = 'field_email';
const FIELD_PHONE_NUMBER = 'field_phone_number';
@@ -86,6 +87,7 @@ module.exports = React.createClass({
// is the one from the first invalid field.
// It's not super ideal that this just calls
// onValidationChange once for each invalid field.
+ // TODO: Change this to trigger new-style validation for an invalid fields.
this.validateField(FIELD_PHONE_NUMBER, ev.type);
this.validateField(FIELD_EMAIL, ev.type);
this.validateField(FIELD_PASSWORD_CONFIRM, ev.type);
@@ -152,6 +154,8 @@ module.exports = React.createClass({
const pwd2 = this.state.passwordConfirm.trim();
const allowEmpty = eventType === "blur";
+ // TODO: Remove rules here as they are converted to new-style validation
+
switch (fieldID) {
case FIELD_EMAIL: {
const email = this.state.email;
@@ -173,12 +177,6 @@ module.exports = React.createClass({
const username = this.state.username;
if (allowEmpty && username === '') {
this.markFieldValid(fieldID, true);
- } else if (!SAFE_LOCALPART_REGEX.test(username)) {
- this.markFieldValid(
- fieldID,
- false,
- "RegistrationForm.ERR_USERNAME_INVALID",
- );
} else if (username == '') {
this.markFieldValid(
fieldID,
@@ -232,11 +230,14 @@ module.exports = React.createClass({
this.setState({
fieldErrors,
});
+ // TODO: Remove outer validation handling once all fields converted to new-style
+ // validation in the form.
this.props.onValidationChange(fieldErrors);
},
_classForField: function(fieldID, ...baseClasses) {
let cls = baseClasses.join(' ');
+ // TODO: Remove this from fields as they are converted to new-style validation.
if (this.state.fieldErrors[fieldID]) {
if (cls) cls += ' ';
cls += 'error';
@@ -291,10 +292,6 @@ module.exports = React.createClass({
});
},
- onUsernameBlur(ev) {
- this.validateField(FIELD_USERNAME, ev.type);
- },
-
onUsernameChange(ev) {
this.setState({
username: ev.target.value,
@@ -325,6 +322,33 @@ module.exports = React.createClass({
});
},
+ renderUsername() {
+ const Field = sdk.getComponent('elements.Field');
+
+ const onValidate = withValidation({
+ description: _t("Use letters, numbers, dashes and underscores only"),
+ rules: [
+ {
+ key: "safeLocalpart",
+ regex: SAFE_LOCALPART_REGEX,
+ invalid: _t("Some characters not allowed"),
+ },
+ ],
+ });
+
+ return