import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
type ValidatorProps = {
- value: string,
- onChange: (isValid: boolean | string) => void;
- render: (hasError: boolean) => React.ReactElement<any>;
- isRequired: boolean;
+ value: string,
+ render: (hasError: boolean) => React.ReactElement<any>;
+ isUniqName?: boolean;
+ validators: Array<(value: string) => string>;
};
-interface ValidatorState {
- isPatternValid: boolean;
- isLengthValid: boolean;
-}
-
-const nameRegEx = /^[a-zA-Z0-9-_ ]+$/;
-const maxInputLength = 60;
-
class Validator extends React.Component<ValidatorProps & WithStyles<CssRules>> {
- state: ValidatorState = {
- isPatternValid: true,
- isLengthValid: true
- };
-
- componentWillReceiveProps(nextProps: ValidatorProps) {
- const { value } = nextProps;
-
- if (this.props.value !== value) {
- this.setState({
- isPatternValid: value.match(nameRegEx),
- isLengthValid: value.length < maxInputLength
- }, () => this.onChange());
+ render() {
+ const { classes, value, isUniqName } = this.props;
+
+ return (
+ <span>
+ {this.props.render(!this.isValid(value))}
+ {isUniqName ? <span className={classes.formInputError}>Project with this name already exists</span> : null}
+ {this.props.validators.map(validate => {
+ const errorMsg = validate(value);
+ return errorMsg ? <span className={classes.formInputError}>{errorMsg}</span> : null;
+ })}
+ </span>
+ );
}
- }
-
- onChange() {
- const { value, onChange, isRequired } = this.props;
- const { isPatternValid, isLengthValid } = this.state;
- const isValid = value && isPatternValid && isLengthValid && (isRequired || (!isRequired && value.length > 0));
- onChange(isValid);
- }
-
- render() {
- const { classes, isRequired, value } = this.props;
- const { isPatternValid, isLengthValid } = this.state;
-
- return (
- <span>
- {this.props.render(!(isPatternValid && isLengthValid) && (isRequired || (!isRequired && value.length > 0)))}
- {!isPatternValid && (isRequired || (!isRequired && value.length > 0)) ? <span className={classes.formInputError}>This field allow only alphanumeric characters, dashes, spaces and underscores.<br /></span> : null}
- {!isLengthValid ? <span className={classes.formInputError}>This field should have max 60 characters.</span> : null}
- </span>
- );
- }
+ isValid(value: string) {
+ return this.props.validators.every(validate => validate(value).length === 0);
+ }
}
+export const required = (value: string) => value.length > 0 ? "" : "This value is required";
+export const maxLength = (max: number) => (value: string) => value.length <= max ? "" : `This field should have max ${max} characters.`;
+export const isUniq = (getError: () => string) => (value: string) => getError() ? "Project with this name already exists" : "";
+
type CssRules = "formInputError";
const styles: StyleRulesCallback<CssRules> = theme => ({
- formInputError: {
- color: "#ff0000",
- marginLeft: "5px",
- fontSize: "11px",
- }
+ formInputError: {
+ color: "#ff0000",
+ marginLeft: "5px",
+ fontSize: "11px",
+ }
});
export default withStyles(styles)(Validator);
\ No newline at end of file