mirror of
https://github.com/opensupports/opensupports.git
synced 2025-07-31 01:35:15 +02:00
[Ivan Diaz] - FrontEnd - Add form validation logic [skip ci]
This commit is contained in:
parent
f06b45948a
commit
7b8012401e
@ -33,8 +33,8 @@ let MainHomePageLoginWidget = React.createClass({
|
|||||||
<Widget className="main-home-page--widget" title="Login">
|
<Widget className="main-home-page--widget" title="Login">
|
||||||
<Form className="login-widget--form" onSubmit={this.handleLoginFormSubmit}>
|
<Form className="login-widget--form" onSubmit={this.handleLoginFormSubmit}>
|
||||||
<div className="login-widget--inputs">
|
<div className="login-widget--inputs">
|
||||||
<Input placeholder="email" name="email" className="login-widget--input" validation="EMAIL"/>
|
<Input placeholder="email" name="email" className="login-widget--input" validation="EMAIL" required/>
|
||||||
<Input placeholder="password" name="password" className="login-widget--input" password/>
|
<Input placeholder="password" name="password" className="login-widget--input" password required/>
|
||||||
<Checkbox name="remember" label="Remember Me" className="login-widget--input"/>
|
<Checkbox name="remember" label="Remember Me" className="login-widget--input"/>
|
||||||
</div>
|
</div>
|
||||||
<div className="login-widget--submit-button">
|
<div className="login-widget--submit-button">
|
||||||
|
39
client/src/core-components/__tests__/input-test.js
Normal file
39
client/src/core-components/__tests__/input-test.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
const Input = require('core-components/input');
|
||||||
|
|
||||||
|
describe('Input component', function () {
|
||||||
|
|
||||||
|
let nativeInput, input;
|
||||||
|
|
||||||
|
function renderInput(props) {
|
||||||
|
input = TestUtils.renderIntoDocument(
|
||||||
|
<Input {...props} />
|
||||||
|
);
|
||||||
|
nativeInput = TestUtils.findRenderedDOMComponentWithTag(input, 'input');
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('when passing props that affects the native input', function () {
|
||||||
|
|
||||||
|
it('should render type text if it has not specified type', function () {
|
||||||
|
renderInput();
|
||||||
|
|
||||||
|
expect(nativeInput.getAttribute('type')).to.equal('text');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render type password if password pass is passed', function () {
|
||||||
|
renderInput({
|
||||||
|
password: true
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(nativeInput.getAttribute('type')).to.equal('password');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render aria-required instead of required', function () {
|
||||||
|
renderInput({
|
||||||
|
required: true
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(nativeInput.getAttribute('required')).to.not.equal('null');
|
||||||
|
expect(nativeInput.getAttribute('aria-required')).to.equal('true');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,4 +1,5 @@
|
|||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
const ReactDOM = require('react-dom');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
const {reactDFS, renderChildrenWithProps} = require('lib-core/react-dfs');
|
const {reactDFS, renderChildrenWithProps} = require('lib-core/react-dfs');
|
||||||
@ -14,23 +15,28 @@ const Form = React.createClass({
|
|||||||
form: {},
|
form: {},
|
||||||
validations: {},
|
validations: {},
|
||||||
errors: {}
|
errors: {}
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
let formState = {};
|
let formState = {};
|
||||||
let validations = {};
|
let validations = {};
|
||||||
|
|
||||||
reactDFS(this.props.children, function (child) {
|
reactDFS(this.props.children, (child) => {
|
||||||
if (child.type === Input) {
|
|
||||||
formState[child.props.name] = child.props.value || '';
|
if (this.isValidInputType(child)) {
|
||||||
validations[child.props.name] = ValidationFactory.getValidator(child.props.validation || 'DEFAULT');
|
if (child.type === Input) {
|
||||||
|
formState[child.props.name] = child.props.value || '';
|
||||||
|
}
|
||||||
|
else if (child.type === Checkbox) {
|
||||||
|
formState[child.props.name] = child.props.checked || false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child.props.required) {
|
||||||
|
validations[child.props.name] = ValidationFactory.getValidator(child.props.validation || 'DEFAULT');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (child.type === Checkbox) {
|
});
|
||||||
formState[child.props.name] = child.props.checked || false;
|
|
||||||
validations[child.props.name] = ValidationFactory.getValidator(child.props.validation || 'DEFAULT');
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
form: formState,
|
form: formState,
|
||||||
@ -75,7 +81,9 @@ const Form = React.createClass({
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if (this.hasFormErrors()) {
|
if (this.hasFormErrors()) {
|
||||||
this.focusFirstErrorField();
|
this.setState({
|
||||||
|
errors: this.validateAllFields()
|
||||||
|
}, this.focusFirstErrorField);
|
||||||
} else if (this.props.onSubmit) {
|
} else if (this.props.onSubmit) {
|
||||||
this.props.onSubmit(this.state.form);
|
this.props.onSubmit(this.state.form);
|
||||||
}
|
}
|
||||||
@ -83,18 +91,15 @@ const Form = React.createClass({
|
|||||||
|
|
||||||
handleInputChange(inputName, type, event) {
|
handleInputChange(inputName, type, event) {
|
||||||
let form = _.clone(this.state.form);
|
let form = _.clone(this.state.form);
|
||||||
let errors = _.clone(this.state.errors);
|
let errors;
|
||||||
let inputValue = event.target.value;
|
|
||||||
|
|
||||||
form[inputName] = inputValue;
|
form[inputName] = event.target.value;
|
||||||
errors[inputName] = this.state.validations[inputName].validate(inputValue, form);
|
|
||||||
|
|
||||||
if (type === Checkbox) {
|
if (type === Checkbox) {
|
||||||
form[inputName] = event.target.checked || false;
|
form[inputName] = event.target.checked || false;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(errors);
|
errors = this.validateField(inputName, form);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
form: form,
|
form: form,
|
||||||
errors: errors
|
errors: errors
|
||||||
@ -109,16 +114,45 @@ const Form = React.createClass({
|
|||||||
let firstErrorField = this.getFirstErrorField();
|
let firstErrorField = this.getFirstErrorField();
|
||||||
|
|
||||||
if (firstErrorField) {
|
if (firstErrorField) {
|
||||||
this.refs[firstErrorField].focus();
|
firstErrorField.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getFirstErrorField() {
|
getFirstErrorField() {
|
||||||
|
let fieldName = _.findKey(this.state.errors);
|
||||||
|
let fieldNode;
|
||||||
|
|
||||||
|
if (fieldName) {
|
||||||
|
fieldNode = ReactDOM.findDOMNode(this.refs[fieldName]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fieldNode;
|
||||||
},
|
},
|
||||||
|
|
||||||
validateAllFields: function () {
|
isValidInputType(child) {
|
||||||
|
return child.type === Input || child.type === Checkbox;
|
||||||
|
},
|
||||||
|
|
||||||
|
validateAllFields() {
|
||||||
|
let form = this.state.form;
|
||||||
|
let inputList = Object.keys(this.state.form);
|
||||||
|
let errors = {};
|
||||||
|
|
||||||
|
_.each(inputList, (inputName) => {
|
||||||
|
errors = this.validateField(inputName, form, errors);
|
||||||
|
});
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
},
|
||||||
|
|
||||||
|
validateField(inputName, form = this.state.form, errors = this.state.errors) {
|
||||||
|
let newErrors = _.clone(errors);
|
||||||
|
|
||||||
|
if (this.state.validations[inputName]) {
|
||||||
|
newErrors[inputName] = this.state.validations[inputName].validate(form[inputName], form);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newErrors;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@ const Input = React.createClass({
|
|||||||
validation: React.PropTypes.string,
|
validation: React.PropTypes.string,
|
||||||
onChange: React.PropTypes.func,
|
onChange: React.PropTypes.func,
|
||||||
inputType: React.PropTypes.string,
|
inputType: React.PropTypes.string,
|
||||||
password: React.PropTypes.bool
|
password: React.PropTypes.bool,
|
||||||
|
required: React.PropTypes.bool
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
@ -22,14 +23,16 @@ const Input = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<label className={this.getClass()}>
|
<label className={this.getClass()}>
|
||||||
<span className="input--label">{this.props.label}</span>
|
<span className="input--label">{this.props.label}</span>
|
||||||
<input {...this.getProps()} className="input--text" />
|
<input {...this.getInputProps()} className="input--text" />
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
getProps() {
|
getInputProps() {
|
||||||
let props = _.clone(this.props);
|
let props = _.clone(this.props);
|
||||||
|
|
||||||
|
props.required = null;
|
||||||
|
props['aria-required'] = this.props.required;
|
||||||
props.type = (this.props.password) ? 'password' : 'text';
|
props.type = (this.props.password) ? 'password' : 'text';
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user