6391e7c5ef4266730d8770ebe4c707b357944e83273285eff399c9a63b5b45288e39662373af9a13af57660da306e0a8d05ea5871b71c70df459aa0ee50170 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <template>
  2. <form class="el-form" :class="[
  3. labelPosition ? 'el-form--label-' + labelPosition : '',
  4. { 'el-form--inline': inline }
  5. ]">
  6. <slot></slot>
  7. </form>
  8. </template>
  9. <script>
  10. import objectAssign from 'element-ui/src/utils/merge';
  11. export default {
  12. name: 'ElForm',
  13. componentName: 'ElForm',
  14. provide() {
  15. return {
  16. elForm: this
  17. };
  18. },
  19. props: {
  20. model: Object,
  21. rules: Object,
  22. labelPosition: String,
  23. labelWidth: String,
  24. labelSuffix: {
  25. type: String,
  26. default: ''
  27. },
  28. inline: Boolean,
  29. inlineMessage: Boolean,
  30. statusIcon: Boolean,
  31. showMessage: {
  32. type: Boolean,
  33. default: true
  34. },
  35. size: String,
  36. disabled: Boolean,
  37. validateOnRuleChange: {
  38. type: Boolean,
  39. default: true
  40. },
  41. hideRequiredAsterisk: {
  42. type: Boolean,
  43. default: false
  44. }
  45. },
  46. watch: {
  47. rules() {
  48. // remove then add event listeners on form-item after form rules change
  49. this.fields.forEach(field => {
  50. field.removeValidateEvents();
  51. field.addValidateEvents();
  52. });
  53. if (this.validateOnRuleChange) {
  54. this.validate(() => {});
  55. }
  56. }
  57. },
  58. computed: {
  59. autoLabelWidth() {
  60. if (!this.potentialLabelWidthArr.length) return 0;
  61. const max = Math.max(...this.potentialLabelWidthArr);
  62. return max ? `${max}px` : '';
  63. }
  64. },
  65. data() {
  66. return {
  67. fields: [],
  68. potentialLabelWidthArr: [] // use this array to calculate auto width
  69. };
  70. },
  71. created() {
  72. this.$on('el.form.addField', (field) => {
  73. if (field) {
  74. this.fields.push(field);
  75. }
  76. });
  77. /* istanbul ignore next */
  78. this.$on('el.form.removeField', (field) => {
  79. if (field.prop) {
  80. this.fields.splice(this.fields.indexOf(field), 1);
  81. }
  82. });
  83. },
  84. methods: {
  85. resetFields() {
  86. if (!this.model) {
  87. console.warn('[Element Warn][Form]model is required for resetFields to work.');
  88. return;
  89. }
  90. this.fields.forEach(field => {
  91. field.resetField();
  92. });
  93. },
  94. clearValidate(props = []) {
  95. const fields = props.length
  96. ? (typeof props === 'string'
  97. ? this.fields.filter(field => props === field.prop)
  98. : this.fields.filter(field => props.indexOf(field.prop) > -1)
  99. ) : this.fields;
  100. fields.forEach(field => {
  101. field.clearValidate();
  102. });
  103. },
  104. validate(callback) {
  105. if (!this.model) {
  106. console.warn('[Element Warn][Form]model is required for validate to work!');
  107. return;
  108. }
  109. let promise;
  110. // if no callback, return promise
  111. if (typeof callback !== 'function' && window.Promise) {
  112. promise = new window.Promise((resolve, reject) => {
  113. callback = function(valid, invalidFields) {
  114. valid ? resolve(valid) : reject(invalidFields);
  115. };
  116. });
  117. }
  118. let valid = true;
  119. let count = 0;
  120. // 如果需要验证的fields为空,调用验证时立刻返回callback
  121. if (this.fields.length === 0 && callback) {
  122. callback(true);
  123. }
  124. let invalidFields = {};
  125. this.fields.forEach(field => {
  126. field.validate('', (message, field) => {
  127. if (message) {
  128. valid = false;
  129. }
  130. invalidFields = objectAssign({}, invalidFields, field);
  131. if (typeof callback === 'function' && ++count === this.fields.length) {
  132. callback(valid, invalidFields);
  133. }
  134. });
  135. });
  136. if (promise) {
  137. return promise;
  138. }
  139. },
  140. validateField(props, cb) {
  141. props = [].concat(props);
  142. const fields = this.fields.filter(field => props.indexOf(field.prop) !== -1);
  143. if (!fields.length) {
  144. console.warn('[Element Warn]please pass correct props!');
  145. return;
  146. }
  147. fields.forEach(field => {
  148. field.validate('', cb);
  149. });
  150. },
  151. getLabelWidthIndex(width) {
  152. const index = this.potentialLabelWidthArr.indexOf(width);
  153. // it's impossible
  154. if (index === -1) {
  155. throw new Error('[ElementForm]unpected width ', width);
  156. }
  157. return index;
  158. },
  159. registerLabelWidth(val, oldVal) {
  160. if (val && oldVal) {
  161. const index = this.getLabelWidthIndex(oldVal);
  162. this.potentialLabelWidthArr.splice(index, 1, val);
  163. } else if (val) {
  164. this.potentialLabelWidthArr.push(val);
  165. }
  166. },
  167. deregisterLabelWidth(val) {
  168. const index = this.getLabelWidthIndex(val);
  169. this.potentialLabelWidthArr.splice(index, 1);
  170. }
  171. }
  172. };
  173. </script>