Skip to content

Commit

Permalink
Merge branch 'feature/async-username-validation' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
gocreating committed Oct 14, 2016
2 parents 1c09229 + 4e098d4 commit 4eff5b5
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ git flow feature finish upgrade-mirror
### v1.0

- [x] Travis Testing
- [ ] Asynchronous redux-form validation (detect duplicate username/email)
- [x] Asynchronous redux-form validation (detect duplicate email)
- [ ] Pagination Mechanism

### v1.0+
Expand Down
17 changes: 17 additions & 0 deletions src/common/actions/formActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import formAPI from '../api/form';
import { pushErrors } from '../actions/errorActions';

export const validateForm = (formName, fieldName, value) => {
return (dispatch, getState) => {
return formAPI(getState().apiEngine)
.form(formName)
.field(fieldName, value)
.validate()
.catch((err) => {
let validationError = {};
dispatch(pushErrors(err));
validationError[fieldName] = 'Unable to validate';
throw validationError;
});
};
};
11 changes: 11 additions & 0 deletions src/common/api/form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default (apiEngine) => ({
form: (formName) => ({
field: (fieldName, value) => ({
validate: () => apiEngine.post(
`/api/forms/${formName}/fields/${fieldName}/validation`, {
data: { value },
}
),
}),
}),
});
20 changes: 19 additions & 1 deletion src/common/components/forms/RegisterForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Field, reduxForm } from 'redux-form';
import Button from 'react-bootstrap/lib/Button';
// import validator from 'validator';
import userAPI from '../../api/user';
import { validateForm } from '../../actions/formActions';
import { pushErrors } from '../../actions/errorActions';
import { Form, FormField, FormFooter } from '../utils/BsForm';

Expand All @@ -24,6 +25,17 @@ const validate = (values) => {
return errors;
};

let asyncValidate = (values, dispatch) => {
return dispatch(validateForm('register', 'email', values.email))
.then((json) => {
let validationError = {};
if (!json.isPassed) {
validationError.email = json.message;
throw validationError;
}
});
};

class RegisterForm extends Component {
constructor(props) {
super(props);
Expand All @@ -46,6 +58,7 @@ class RegisterForm extends Component {
const {
handleSubmit,
pristine,
asyncValidating,
submitting,
invalid,
} = this.props;
Expand Down Expand Up @@ -74,7 +87,10 @@ class RegisterForm extends Component {
placeholder="Password"
/>
<FormFooter>
<Button type="submit" disabled={pristine || submitting || invalid}>
<Button
type="submit"
disabled={pristine || !!asyncValidating || submitting || invalid}
>
Register
</Button>
</FormFooter>
Expand All @@ -91,4 +107,6 @@ RegisterForm.contextTypes = {
export default reduxForm({
form: 'register',
validate,
asyncValidate,
asyncBlurFields: ['email'],
})(RegisterForm);
23 changes: 23 additions & 0 deletions src/server/controllers/formValidation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { handleDbError } from '../decorators/handleError';
import User from '../models/User';

export default {
register: {
email(req, res) {
User.findOne({
'email.value': req.body.value,
}, handleDbError(res)((user) => {
if (user) {
res.json({
isPassed: false,
message: 'The email is already registered',
});
} else {
res.json({
isPassed: true,
});
}
}));
},
},
};
5 changes: 5 additions & 0 deletions src/server/routes/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import bodyParser from '../middlewares/bodyParser';
import authRequired from '../middlewares/authRequired';
import fileUpload from '../middlewares/fileUpload';
import userController from '../controllers/user';
import formValidationController from '../controllers/formValidation';
import localeController from '../controllers/locale';
import todoController from '../controllers/todo';

Expand All @@ -24,6 +25,10 @@ export default ({ app }) => {
filename: 'avatar.jpg',
}).single('avatar'),
userController.uploadAvatar);
app.post('/api/forms/register/fields/email/validation',
bodyParser.json,
formValidationController.register.email
);
app.get('/api/locale/:locale', localeController.show);
app.post('/api/todo', bodyParser.json, todoController.create);
app.get('/api/todo', todoController.list);
Expand Down

0 comments on commit 4eff5b5

Please sign in to comment.