अद्यतन: यह उत्तर पुराना है। यदि आप कर सकते हैं तो मिश्रण से दूर रहें। मैंने तुम्हे चेतावनी दी थी। मैंने तुम्हे चेताया था!
मिक्सिंस डेड। लंबे समय तक जीवित रचना
सबसे पहले, मैंने इसके लिए सब-पार्टनर्स का उपयोग करने की कोशिश की और निकालने FormWidget
और InputWidget
। हालाँकि, मैंने इस दृष्टिकोण को आधा छोड़ दिया क्योंकि मैं उत्पन्न input
s और उनके राज्य पर बेहतर नियंत्रण चाहता था ।
दो लेख जिनसे मुझे सबसे ज्यादा मदद मिली:
यह पता चला कि मुझे केवल दो (अलग) मिश्रण लिखने की जरूरत थी: 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
हैंडलर से कह सकते हैं ।