अद्यतन: यह उत्तर पुराना है। यदि आप कर सकते हैं तो मिश्रण से दूर रहें। मैंने तुम्हे चेतावनी दी थी। मैंने तुम्हे चेताया था!
मिक्सिंस डेड। लंबे समय तक जीवित रचना
सबसे पहले, मैंने इसके लिए सब-पार्टनर्स का उपयोग करने की कोशिश की और निकालने FormWidgetऔर InputWidget। हालाँकि, मैंने इस दृष्टिकोण को आधा छोड़ दिया क्योंकि मैं उत्पन्न inputs और उनके राज्य पर बेहतर नियंत्रण चाहता था ।
दो लेख जिनसे मुझे सबसे ज्यादा मदद मिली:
यह पता चला कि मुझे केवल दो (अलग) मिश्रण लिखने की जरूरत थी: ValidationMixinऔर FormMixin।
यहां बताया गया है कि मैंने उन्हें कैसे अलग किया।
ValidationMixin
सत्यापन मिश्रण अपने राज्य के कुछ गुणों पर अपने सत्यापनकर्ता कार्यों को चलाने के लिए सुविधा विधियों को जोड़ता है और state.errorsसरणी में "त्रुटि" गुणों को संग्रहीत करता है ताकि आप संबंधित क्षेत्रों को उजागर कर सकें।
define(function () {
'use strict';
var _ = require('underscore');
var ValidationMixin = {
getInitialState: function () {
return {
errors: []
};
},
componentWillMount: function () {
this.assertValidatorsDefined();
},
assertValidatorsDefined: function () {
if (!this.validators) {
throw new Error('ValidatorMixin requires this.validators to be defined on the component.');
}
_.each(_.keys(this.validators), function (key) {
var validator = this.validators[key];
if (!_.has(this.state, key)) {
throw new Error('Key "' + key + '" is defined in this.validators but not present in initial state.');
}
if (!_.isFunction(validator)) {
throw new Error('Validator for key "' + key + '" is not a function.');
}
}, this);
},
hasError: function (key) {
return _.contains(this.state.errors, key);
},
resetError: function (key) {
this.setState({
'errors': _.without(this.state.errors, key)
});
},
validate: function () {
var errors = _.filter(_.keys(this.validators), function (key) {
var validator = this.validators[key],
value = this.state[key];
return !validator(value);
}, this);
this.setState({
'errors': errors
});
return _.isEmpty(errors);
}
};
return ValidationMixin;
});
प्रयोग
ValidationMixinतीन तरीकों है: validate, hasErrorऔर resetError।
यह वर्ग को validatorsवस्तु के समान परिभाषित करने की उम्मीद करता है propTypes:
var JoinWidget = React.createClass({
mixins: [React.addons.LinkedStateMixin, ValidationMixin, FormMixin],
validators: {
email: Misc.isValidEmail,
name: function (name) {
return name.length > 0;
}
},
// ...
});
जब उपयोगकर्ता सबमिट बटन दबाता है, तो मैं कॉल करता हूं validate। कॉल validateप्रत्येक सत्यापनकर्ता को चलाएगी और this.state.errorsउस सरणी के साथ पॉप्युलेट होगी जिसमें सत्यापन विफल होने वाले गुणों की कुंजी है।
अपनी renderपद्धति में, मैं hasErrorखेतों के लिए सही CSS क्लास उत्पन्न करने के लिए उपयोग करता हूं । जब उपयोगकर्ता क्षेत्र के अंदर ध्यान केंद्रित करता है, तो मैं resetErrorअगले validateकॉल तक त्रुटि हाइलाइट को दूर करने के लिए कहता हूं ।
renderInput: function (key, options) {
var classSet = {
'Form-control': true,
'Form-control--error': this.hasError(key)
};
return (
<input key={key}
type={options.type}
placeholder={options.placeholder}
className={React.addons.classSet(classSet)}
valueLink={this.linkState(key)}
onFocus={_.partial(this.resetError, key)} />
);
}
FormMixin
फॉर्म मिक्सिन फॉर्म स्टेट (संपादन योग्य, सबमिट करना, सबमिट करना) बनाता है। अनुरोध भेजे जाने के दौरान इनपुट और बटनों को अक्षम करने के लिए आप इसका उपयोग कर सकते हैं, और जब यह भेजा जाता है तो इसी के अनुसार अपने विचार को अपडेट करने के लिए।
define(function () {
'use strict';
var _ = require('underscore');
var EDITABLE_STATE = 'editable',
SUBMITTING_STATE = 'submitting',
SUBMITTED_STATE = 'submitted';
var FormMixin = {
getInitialState: function () {
return {
formState: EDITABLE_STATE
};
},
componentDidMount: function () {
if (!_.isFunction(this.sendRequest)) {
throw new Error('To use FormMixin, you must implement sendRequest.');
}
},
getFormState: function () {
return this.state.formState;
},
setFormState: function (formState) {
this.setState({
formState: formState
});
},
getFormError: function () {
return this.state.formError;
},
setFormError: function (formError) {
this.setState({
formError: formError
});
},
isFormEditable: function () {
return this.getFormState() === EDITABLE_STATE;
},
isFormSubmitting: function () {
return this.getFormState() === SUBMITTING_STATE;
},
isFormSubmitted: function () {
return this.getFormState() === SUBMITTED_STATE;
},
submitForm: function () {
if (!this.isFormEditable()) {
throw new Error('Form can only be submitted when in editable state.');
}
this.setFormState(SUBMITTING_STATE);
this.setFormError(undefined);
this.sendRequest()
.bind(this)
.then(function () {
this.setFormState(SUBMITTED_STATE);
})
.catch(function (err) {
this.setFormState(EDITABLE_STATE);
this.setFormError(err);
})
.done();
}
};
return FormMixin;
});
प्रयोग
यह घटक को एक विधि प्रदान करने की उम्मीद करता है: sendRequestजिसे ब्लूबर्ड वादा वापस करना चाहिए। (यह क्यू या अन्य वादा पुस्तकालय के साथ काम करने के लिए इसे संशोधित करने के लिए तुच्छ है।)
यह इस तरह के रूप में सुविधा के तरीके प्रदान करता है isFormEditable, isFormSubmittingऔर isFormSubmitted। यह अनुरोध को बंद करने के लिए एक विधि भी प्रदान करता है submitForm:। आप इसे फॉर्म बटन के onClickहैंडलर से कह सकते हैं ।