อัปเดต: คำตอบนี้ล้าสมัย อยู่ห่างจากมิกซ์อินถ้าทำได้ ฉันเตือนคุณแล้ว!
Mixins จะตาย องค์ประกอบที่มีชีวิตยาวนาน
ตอนแรกฉันพยายามใช้ส่วนประกอบย่อยสำหรับสิ่งนี้และแยกFormWidget
และInputWidget
. อย่างไรก็ตามฉันละทิ้งแนวทางนี้ไปกลางคันเพราะฉันต้องการการควบคุมที่ดีขึ้นสำหรับinput
s ที่สร้างขึ้นและสถานะของพวกเขา
สองบทความที่ช่วยฉันมากที่สุด:
มันกลับกลายเป็นว่าผมจำเป็นเท่านั้นที่จะเขียนสอง (แตกต่างกัน) mixins: และ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
แบบฟอร์ม mixin จัดการกับสถานะของฟอร์ม (แก้ไขได้, ส่ง, ส่ง) คุณสามารถใช้เพื่อปิดใช้งานอินพุตและปุ่มในขณะที่กำลังส่งคำขอและเพื่ออัปเดตมุมมองของคุณให้สอดคล้องกันเมื่อถูกส่ง
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
ซึ่งควรส่งคืนคำสัญญาของ Bluebird (เป็นเรื่องเล็กน้อยที่จะแก้ไขให้ทำงานกับ Q หรือไลบรารีสัญญาอื่น ๆ )
มันมีวิธีการอำนวยความสะดวกเช่นisFormEditable
, และisFormSubmitting
นอกจากนี้ยังมีวิธีการที่จะเตะออกคำขอ:isFormSubmitted
submitForm
คุณสามารถเรียกใช้จากonClick
ตัวจัดการปุ่มแบบฟอร์ม