PageRenderTime 80ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/components/SurveyForm/SurveyForm.js

https://gitlab.com/fbi/birs
JavaScript | 140 lines | 132 code | 7 blank | 1 comment | 13 complexity | 4a1544a277cdf30281f12b409fd56cc2 MD5 | raw file
  1. import React, {Component, PropTypes} from 'react';
  2. import {reduxForm} from 'redux-form';
  3. import surveyValidation from './surveyValidation';
  4. function asyncValidate(data) {
  5. // TODO: figure out a way to move this to the server. need an instance of ApiClient
  6. if (!data.email) {
  7. return Promise.resolve({});
  8. }
  9. return new Promise((resolve, reject) => {
  10. setTimeout(() => {
  11. const errors = {};
  12. let valid = true;
  13. if (~['bobby@gmail.com', 'timmy@microsoft.com'].indexOf(data.email)) {
  14. errors.email = 'Email address already used';
  15. valid = false;
  16. }
  17. if (valid) {
  18. resolve();
  19. } else {
  20. reject(errors);
  21. }
  22. }, 1000);
  23. });
  24. }
  25. @reduxForm({
  26. form: 'survey',
  27. fields: ['name', 'email', 'occupation', 'currentlyEmployed', 'sex'],
  28. validate: surveyValidation,
  29. asyncValidate,
  30. asyncBlurFields: ['email']
  31. })
  32. export default
  33. class SurveyForm extends Component {
  34. static propTypes = {
  35. active: PropTypes.string,
  36. asyncValidating: PropTypes.bool.isRequired,
  37. fields: PropTypes.object.isRequired,
  38. dirty: PropTypes.bool.isRequired,
  39. handleSubmit: PropTypes.func.isRequired,
  40. resetForm: PropTypes.func.isRequired,
  41. invalid: PropTypes.bool.isRequired,
  42. pristine: PropTypes.bool.isRequired,
  43. valid: PropTypes.bool.isRequired
  44. }
  45. render() {
  46. const {
  47. asyncValidating,
  48. dirty,
  49. fields: {name, email, occupation, currentlyEmployed, sex},
  50. active,
  51. handleSubmit,
  52. invalid,
  53. resetForm,
  54. pristine,
  55. valid
  56. } = this.props;
  57. const styles = require('./SurveyForm.scss');
  58. const renderInput = (field, label, showAsyncValidating) =>
  59. <div className={'form-group' + (field.error && field.touched ? ' has-error' : '')}>
  60. <label htmlFor={field.name} className="col-sm-2">{label}</label>
  61. <div className={'col-sm-8 ' + styles.inputGroup}>
  62. {showAsyncValidating && asyncValidating && <i className={'fa fa-cog fa-spin ' + styles.cog}/>}
  63. <input type="text" className="form-control" id={field.name} {...field}/>
  64. {field.error && field.touched && <div className="text-danger">{field.error}</div>}
  65. <div className={styles.flags}>
  66. {field.dirty && <span className={styles.dirty} title="Dirty">D</span>}
  67. {field.active && <span className={styles.active} title="Active">A</span>}
  68. {field.visited && <span className={styles.visited} title="Visited">V</span>}
  69. {field.touched && <span className={styles.touched} title="Touched">T</span>}
  70. </div>
  71. </div>
  72. </div>;
  73. return (
  74. <div>
  75. <form className="form-horizontal" onSubmit={handleSubmit}>
  76. {renderInput(name, 'Full Name')}
  77. {renderInput(email, 'Email', true)}
  78. {renderInput(occupation, 'Occupation')}
  79. <div className="form-group">
  80. <label htmlFor="currentlyEmployed" className="col-sm-2">Currently Employed?</label>
  81. <div className="col-sm-8">
  82. <input type="checkbox" id="currentlyEmployed" {...currentlyEmployed}/>
  83. </div>
  84. </div>
  85. <div className="form-group">
  86. <label className="col-sm-2">Sex</label>
  87. <div className="col-sm-8">
  88. <input type="radio" id="sex-male" {...sex} value="male" checked={sex.value === 'male'}/>
  89. <label htmlFor="sex-male" className={styles.radioLabel}>Male</label>
  90. <input type="radio" id="sex-female" {...sex} value="female" checked={sex.value === 'female'}/>
  91. <label htmlFor="sex-female" className={styles.radioLabel}>Female</label>
  92. </div>
  93. </div>
  94. <div className="form-group">
  95. <div className="col-sm-offset-2 col-sm-10">
  96. <button className="btn btn-success" onClick={handleSubmit}>
  97. <i className="fa fa-paper-plane"/> Submit
  98. </button>
  99. <button className="btn btn-warning" onClick={resetForm} style={{marginLeft: 15}}>
  100. <i className="fa fa-undo"/> Reset
  101. </button>
  102. </div>
  103. </div>
  104. </form>
  105. <h4>Props from redux-form</h4>
  106. <table className="table table-striped">
  107. <tbody>
  108. <tr>
  109. <th>Active Field</th>
  110. <td>{active}</td>
  111. </tr>
  112. <tr>
  113. <th>Dirty</th>
  114. <td className={dirty ? 'success' : 'danger'}>{dirty ? 'true' : 'false'}</td>
  115. </tr>
  116. <tr>
  117. <th>Pristine</th>
  118. <td className={pristine ? 'success' : 'danger'}>{pristine ? 'true' : 'false'}</td>
  119. </tr>
  120. <tr>
  121. <th>Valid</th>
  122. <td className={valid ? 'success' : 'danger'}>{valid ? 'true' : 'false'}</td>
  123. </tr>
  124. <tr>
  125. <th>Invalid</th>
  126. <td className={invalid ? 'success' : 'danger'}>{invalid ? 'true' : 'false'}</td>
  127. </tr>
  128. </tbody>
  129. </table>
  130. </div>
  131. );
  132. }
  133. }