उन लोगों के लिए बस एक और बात जो ओवरसाइज़्ड लाइब्रेरी का उपयोग किए बिना पूरी तरह से नियंत्रित फ़ॉर्म घटक बनाना चाहते हैं।
ReduxFormHelper - एक छोटा ES6 वर्ग, 100 से कम लाइनें:
class ReduxFormHelper {
constructor(props = {}) {
let {formModel, onUpdateForm} = props
this.props = typeof formModel === 'object' &&
typeof onUpdateForm === 'function' && {formModel, onUpdateForm}
}
resetForm (defaults = {}) {
if (!this.props) return false
let {formModel, onUpdateForm} = this.props
let data = {}, errors = {_flag: false}
for (let name in formModel) {
data[name] = name in defaults? defaults[name] :
('default' in formModel[name]? formModel[name].default : '')
errors[name] = false
}
onUpdateForm(data, errors)
}
processField (event) {
if (!this.props || !event.target) return false
let {formModel, onUpdateForm} = this.props
let {name, value, error, within} = this._processField(event.target, formModel)
let data = {}, errors = {_flag: false}
if (name) {
value !== false && within && (data[name] = value)
errors[name] = error
}
onUpdateForm(data, errors)
return !error && data
}
processForm (event) {
if (!this.props || !event.target) return false
let form = event.target
if (!form || !form.elements) return false
let fields = form.elements
let {formModel, onUpdateForm} = this.props
let data = {}, errors = {}, ret = {}, flag = false
for (let n = fields.length, i = 0; i < n; i++) {
let {name, value, error, within} = this._processField(fields[i], formModel)
if (name) {
value !== false && within && (data[name] = value)
value !== false && !error && (ret[name] = value)
errors[name] = error
error && (flag = true)
}
}
errors._flag = flag
onUpdateForm(data, errors)
return !flag && ret
}
_processField (field, formModel) {
if (!field || !field.name || !('value' in field))
return {name: false, value: false, error: false, within: false}
let name = field.name
let value = field.value
if (!formModel || !formModel[name])
return {name, value, error: false, within: false}
let model = formModel[name]
if (model.required && value === '')
return {name, value, error: 'missing', within: true}
if (model.validate && value !== '') {
let fn = model.validate
if (typeof fn === 'function' && !fn(value))
return {name, value, error: 'invalid', within: true}
}
if (model.numeric && isNaN(value = Number(value)))
return {name, value: 0, error: 'invalid', within: true}
return {name, value, error: false, within: true}
}
}
यह आपके लिए सभी काम नहीं करता है। हालांकि यह एक नियंत्रित रूप घटक के निर्माण, सत्यापन और हैंडलिंग की सुविधा प्रदान करता है। आप अपनी परियोजना में या इसके बजाय उपरोक्त कोड को कॉपी और पेस्ट कर सकते हैं, संबंधित पुस्तकालय - redux-form-helper
(प्लग!) शामिल करें।
कैसे इस्तेमाल करे
पहला चरण Redux राज्य में विशिष्ट डेटा जोड़ रहा है जो हमारे फॉर्म की स्थिति का प्रतिनिधित्व करेगा। इन आंकड़ों में वर्तमान फ़ील्ड मान और साथ ही प्रपत्र में प्रत्येक फ़ील्ड के लिए त्रुटि ध्वज के सेट शामिल होंगे।
प्रपत्र स्थिति को मौजूदा reducer में जोड़ा जा सकता है या एक अलग reducer में परिभाषित किया जा सकता है।
इसके अलावा फॉर्म स्टेट के अद्यतन के साथ-साथ संबंधित एक्शन क्रिएटर के लिए विशेष कार्रवाई को परिभाषित करना आवश्यक है।
क्रिया उदाहरण :
export const FORM_UPDATE = 'FORM_UPDATE'
export const doFormUpdate = (data, errors) => {
return { type: FORM_UPDATE, data, errors }
}
...
Reducer उदाहरण :
...
const initialState = {
formData: {
field1: '',
...
},
formErrors: {
},
...
}
export default function reducer (state = initialState, action) {
switch (action.type) {
case FORM_UPDATE:
return {
...ret,
formData: Object.assign({}, formData, action.data || {}),
formErrors: Object.assign({}, formErrors, action.errors || {})
}
...
}
}
दूसरा और अंतिम चरण हमारे फॉर्म के लिए एक कंटेनर घटक बनाता है और इसे Redux राज्य और क्रियाओं के संबंधित भाग से जोड़ता है।
इसके अलावा, हमें एक फॉर्म मॉडल को परिभाषित करने की आवश्यकता है जो फॉर्म फ़ील्ड की मान्यता को निर्दिष्ट करता है। अब हम ReduxFormHelper
घटक के एक सदस्य के रूप में ऑब्जेक्ट को त्वरित करते हैं और वहां हमारे फॉर्म मॉडल और फॉर्म स्टेट की कॉलबैक प्रेषण अपडेट को पास करते हैं।
तब घटक के दशक में render()
विधि हम प्रत्येक क्षेत्र के लिए बाध्य करने के लिए है onChange
और फ़ॉर्म की onSubmit
के साथ घटनाओं processField()
और processForm()
राज्य में प्रपत्र त्रुटि झंडे के आधार पर प्रत्येक क्षेत्र के लिए तरीके क्रमशः के साथ ही प्रदर्शन त्रुटि ब्लॉक।
नीचे दिया गया उदाहरण ट्विटर बूटस्ट्रैप फ्रेमवर्क से CSS का उपयोग करता है।
कंटेनर घटक उदाहरण :
import React, {Component} from 'react';
import {connect} from 'react-redux'
import ReduxFormHelper from 'redux-form-helper'
class MyForm extends Component {
constructor(props) {
super(props);
this.helper = new ReduxFormHelper(props)
this.helper.resetForm();
}
onChange(e) {
this.helper.processField(e)
}
onSubmit(e) {
e.preventDefault()
let {onSubmitForm} = this.props
let ret = this.helper.processForm(e)
ret && onSubmitForm(ret)
}
render() {
let {formData, formErrors} = this.props
return (
<div>
{!!formErrors._flag &&
<div className="alert" role="alert">
Form has one or more errors.
</div>
}
<form onSubmit={this.onSubmit.bind(this)} >
<div className={'form-group' + (formErrors['field1']? ' has-error': '')}>
<label>Field 1 *</label>
<input type="text" name="field1" value={formData.field1} onChange={this.onChange.bind(this)} className="form-control" />
{!!formErrors['field1'] &&
<span className="help-block">
{formErrors['field1'] === 'invalid'? 'Must be a string of 2-50 characters' : 'Required field'}
</span>
}
</div>
...
<button type="submit" className="btn btn-default">Submit</button>
</form>
</div>
)
}
}
const formModel = {
field1: {
required: true,
validate: (value) => value.length >= 2 && value.length <= 50
},
...
}
function mapStateToProps (state) {
return {
formData: state.formData, formErrors: state.formErrors,
formModel
}
}
function mapDispatchToProps (dispatch) {
return {
onUpdateForm: (data, errors) => {
dispatch(doFormUpdate(data, errors))
},
onSubmitForm: (data) => {
// dispatch some action which somehow updates state with form data
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyForm)
डेमो
redux-forms
? मैं सोच रहा हूँ कि प्रतिक्रिया-रूपों की तुलना में वह बॉयलरप्लेट तराजू कैसे है