form.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import React from 'react';
  2. import { required } from 'misago/utils/validators';
  3. import snackbar from 'misago/services/snackbar'; // jshint ignore:line
  4. let validateRequired = required();
  5. export default class extends React.Component {
  6. validate() {
  7. let errors = {};
  8. if (!this.state.validators) {
  9. return errors;
  10. }
  11. let validators = {
  12. required: this.state.validators.required || this.state.validators,
  13. optional: this.state.validators.optional || {}
  14. };
  15. let validatedFields = [];
  16. // add required fields to validation
  17. for (let name in validators.required) {
  18. if (validators.required.hasOwnProperty(name) &&
  19. validators.required[name]) {
  20. validatedFields.push(name);
  21. }
  22. }
  23. // add optional fields to validation
  24. for (let name in validators.optional) {
  25. if (validators.optional.hasOwnProperty(name) &&
  26. validators.optional[name]) {
  27. validatedFields.push(name);
  28. }
  29. }
  30. // validate fields values
  31. for (let i in validatedFields) {
  32. let name = validatedFields[i];
  33. let fieldErrors = this.validateField(name, this.state[name]);
  34. if (fieldErrors === null) {
  35. errors[name] = null;
  36. } else if (fieldErrors) {
  37. errors[name] = fieldErrors;
  38. }
  39. }
  40. return errors;
  41. }
  42. isValid() {
  43. let errors = this.validate();
  44. for (let field in errors) {
  45. if (errors.hasOwnProperty(field)) {
  46. if (errors[field] !== null) {
  47. return false;
  48. }
  49. }
  50. }
  51. return true;
  52. }
  53. validateField(name, value) {
  54. let errors = [];
  55. if (!this.state.validators) {
  56. return errors;
  57. }
  58. let validators = {
  59. required: (this.state.validators.required || this.state.validators)[name],
  60. optional: (this.state.validators.optional || {})[name]
  61. };
  62. let requiredError = validateRequired(value) || false;
  63. if (validators.required) {
  64. if (requiredError) {
  65. errors = [requiredError];
  66. } else {
  67. for (let i in validators.required) {
  68. let validationError = validators.required[i](value);
  69. if (validationError) {
  70. errors.push(validationError);
  71. }
  72. }
  73. }
  74. return errors.length ? errors : null;
  75. } else if (requiredError === false && validators.optional) {
  76. for (let i in validators.optional) {
  77. let validationError = validators.optional[i](value);
  78. if (validationError) {
  79. errors.push(validationError);
  80. }
  81. }
  82. return errors.length ? errors : null;
  83. }
  84. return false; // false === field wasn't validated
  85. }
  86. /* jshint ignore:start */
  87. bindInput = (name) => {
  88. return (event) => {
  89. this.changeValue(name, event.target.value);
  90. }
  91. };
  92. changeValue = (name, value) => {
  93. let newState = {
  94. [name]: value
  95. };
  96. const formErrors = this.state.errors || {};
  97. formErrors[name] = this.validateField(name, newState[name]);
  98. newState.errors = formErrors;
  99. this.setState(newState);
  100. };
  101. clean() {
  102. return true;
  103. }
  104. send() {
  105. return null;
  106. }
  107. handleSuccess(success) {
  108. return;
  109. }
  110. handleError(rejection) {
  111. snackbar.apiError(rejection);
  112. }
  113. handleSubmit = (event) => {
  114. // we don't reload page on submissions
  115. event.preventDefault()
  116. if (this.state.isLoading) {
  117. return;
  118. }
  119. if (this.clean()) {
  120. this.setState({isLoading: true});
  121. let promise = this.send();
  122. if (promise) {
  123. promise.then((success) => {
  124. this.setState({isLoading: false});
  125. this.handleSuccess(success);
  126. }, (rejection) => {
  127. this.setState({isLoading: false});
  128. this.handleError(rejection);
  129. });
  130. } else {
  131. this.setState({isLoading: false});
  132. }
  133. }
  134. };
  135. /* jshint ignore:end */
  136. }