2015-09-23 4 views
12

Ich habe ein Formular mit einer Anzahl von Eingängen, und ich möchte die Werte der Eingänge in meinem Zustand sammeln, ohne eine onChange oder benutzerdefinierte Komponente für jeden Eingang zu definieren.Plug-in oder Muster für den Umgang mit großen Formen in React?

Reagieren hat ein offizielles Add-On LinkedStatesMixin, die aus auf dem Weg zu sein scheint, und ist nur eine Teillösung (Optionsfeld Gruppen, zum Beispiel fehlt):

https://github.com/facebook/react/issues/2302

https://github.com/facebook/react/issues/3573

In der Zwischenzeit kommt von Angular und Ember eine elegante und präzise API zum Einrichten von Eingabebindungen, die in einem Front-End-Framework ein Muss ist.

Was ist der reaktionsstärkste Weg, dies zu erreichen, ohne die veraltete LinkedStatesMixin zu verwenden?

Antwort

0

Dies ist eine Möglichkeit, dies zu tun. Dies ist von https://github.com/calitek/ReactPatterns React.13.Common/FormInputs.

jInput.js

import React, {Component} from 'react'; 

    class JInputRender extends Component { 
     binder(...methods) { methods.forEach((method) => this[method] = this[method].bind(this)); } 

     render() { 
      var inputSty = this.props.input.style ? this.props.input.style : {color: 'red'}; 
      var textValue = this.state.textValue; 
      var colorValue = this.props.input.colorValue ? this.props.input.colorValue : '#1A3212'; 
      var checkedValue = (this.props.input.checkedValue != null) ? this.props.input.checkedValue : false; 
      var numberValue = this.props.input.numberValue ? this.props.input.numberValue : 0; 
      var radioValue = this.props.input.radioValue ? this.props.input.radioValue : ''; 
      var radioChecked = (this.props.input.radioChecked != null) ? this.props.input.radioChecked : false; 
      var min = this.props.input.min ? this.props.input.min : 0; 
      var max = this.props.input.max ? this.props.input.max : 100; 
      var step = this.props.input.step ? this.props.input.step : 1; 
      var inputType = this.props.input.type ? this.props.input.type : 'text'; 

      var returnRadio = (
        <input 
         type={inputType} 
         ref='inputRef' 
         style={inputSty} 
         checked={radioChecked} 
         value={radioValue} 
         onChange={this.handleValueChange} /> 
       ) 

      var returnChecked = (
        <input 
         type={inputType} 
         ref='inputRef' 
         style={inputSty} 
         checked={checkedValue} 
         onChange={this.handleCheckedChange} /> 
       ) 

      var returnColor = (
        <input 
         type={inputType} 
         ref='inputRef' 
         style={inputSty} 
         value={colorValue} 
         onChange={this.handleValueChange} /> 
       ) 

      var returnNumber = (
        <input 
         type={inputType} 
         ref='inputRef' 
         style={inputSty} 
         value={numberValue} 
         min={min} max={max} step={step} 
         onChange={this.handleValueChange} /> 
       ) 

      var returnText = (
        <input 
         type={inputType} 
         ref='inputRef' 
         style={inputSty} 
         value={textValue} 
         onChange={this.handleTextValueChange} /> 
       ) 
      var returnIt; 
      switch (inputType) { 
       case 'checkbox': returnIt = returnChecked; break; 
       case 'radio': returnIt = returnRadio; break; 
       case 'color': returnIt = returnColor; break; 
       case 'number': 
       case 'range': returnIt = returnNumber; break; 
       default: returnIt = returnText; break; 
      } 

      return (returnIt); 
     } 
    } 

    export default class JInput extends JInputRender { 
     constructor() { 
      super(); 
      this.state = {textValue: ''}; 
      this.binder('handleCheckedChange', 'handleTextValueChange', 'handleValueChange'); 
     } 

     componentDidMount() { 
      if (this.props.input.textValue) this.setState({textValue: this.props.input.textValue}); 
      if (this.props.input.focus) React.findDOMNode(this.refs.inputRef).focus(); 
     } 
     componentWillReceiveProps(nextProps) { 
      if (nextProps.input.textValue && (this.state.textValue != nextProps.input.textValue)) 
       {this.setState({textValue: nextProps.input.textValue});} 
     } 
     handleCheckedChange(event) { this.props.handleChange(this.props.input.name, event.target.checked); } 
     handleTextValueChange(event) { 
      var newValue = event.target.value; 
      this.setState({textValue: newValue}); 
      this.props.handleChange(this.props.input.name, newValue); 
     } 
     handleValueChange(event) { this.props.handleChange(this.props.input.name, event.target.value); } 
    } 

app.ctrl.js. Überspringen Sie einfach das JRadioGroup-Zeug.

import React, {Component} from 'react'; 

    import Actions from './../flux/Actions'; 
    import JInput from './common/jInput'; 
    import JRadioGroup from './common/jRadioGroup'; 

    import BasicStore from './../flux/Basic.Store'; 

    var AppCtrlSty = { 
     height: '100%', 
     padding: '0 10px 0 0' 
    } 

    var checkBoxSty = { 
     boxSizing: 'border-box', 
     display: 'inline-block', 
     lineHeight: '18px', 
     marginLeft: '2px', 
     outline: 'none', 
     position: 'relative' 
    }; 

    var radioSty = {color: "blue"} 

    var input3Sty = {color: 'green'}; 

    var inputLabel = {margin: '0 5px'}; 

    var textInput1 = {name: 'text', type: 'text', textValue: '', focus: true}; 
    var checkInput1 = {name: 'checkbox', type: 'checkbox', style: checkBoxSty}; 
    var colorInput = {name: 'color', type: 'color'}; 
    var numberInput = {name: 'number', type: 'number', min: 0, max: 100}; 
    var rangeInput = {name: 'range', type: 'range', min: 0, max: 100}; 

    var radioInput1 = {name: 'radioGroup', type: 'radio', radioValue: 'set'}; 
    var radioInput2 = {name: 'radioGroup', type: 'radio', radioValue: 'setkey'}; 
    var radioInput3 = {name: 'radioGroup', type: 'radio', radioValue: 'key'}; 

    class AppCtrlRender extends Component { 
     binder(...methods) { methods.forEach((method) => this[method] = this[method].bind(this)); } 

     render() { 
      var inputData = this.state.data; 

      textInput1.textValue = inputData.text; 
      checkInput1.checkedValue = inputData.checkbox; 
      colorInput.colorValue = inputData.color; 
      numberInput.numberValue = inputData.number; 
      rangeInput.numberValue = inputData.range; 

      radioInput1.radioChecked = inputData.radioGroup == 'set'; 
      radioInput2.radioChecked = inputData.radioGroup == 'setkey'; 
      radioInput3.radioChecked = inputData.radioGroup == 'key'; 

      var selected = inputData.checkbox ? 'true' : 'false'; 
      var radioGroupName1 = 'key1'; //must be distinct for each use of JRadioGroup 
      var radioValue = inputData.radioGroup; 
      return (
       <div id='AppCtrlSty' style={AppCtrlSty}> 
        React 1.3 Form input<br/><br/> 
        Text: <JInput input={textInput1} handleChange={this.handleValueChange} /><br/><br/> 
        Checkbox: <JInput input={checkInput1} handleChange={this.handleValueChange} /> Value: {selected}<br/><br/> 
        Color: <JInput input={colorInput} handleChange={this.handleValueChange} /> Value: {colorInput.colorValue}<br/><br/> 
        Number: <JInput input={numberInput} handleChange={this.handleValueChange} /> Value: {numberInput.numberValue}<br/><br/> 
        Range: <JInput input={rangeInput} handleChange={this.handleValueChange} /> Value: {rangeInput.numberValue}<br/><br/> 
       <JRadioGroup name={radioGroupName1} value={radioValue} ref="keyGroup" onChange={this.handleRadioChange}> 
       <div>Radio Group: 
        <label id='inputLabel1' style={inputLabel}> 
        <input type="radio" value="set" /> Set 
        </label> 
        <label id='inputLabel2' style={inputLabel}> 
        <input type="radio" value="setkey"/> Set/Key 
        </label> 
        <label id='inputLabel3' style={inputLabel}> 
        <input type="radio" value="key"/> Key 
        </label> 
       </div> 
       </JRadioGroup><br/><br/> 

        Radio Input: &nbsp; 
        <JInput input={radioInput1} handleChange={this.handleValueChange} /> Set &nbsp; 
        <JInput input={radioInput2} handleChange={this.handleValueChange} /> Set/Key &nbsp; 
        <JInput input={radioInput3} handleChange={this.handleValueChange} /> Key &nbsp; 
        Value: {radioValue} 
       </div> 
      ); 
     } 
    } 

    function getState() { return {data: BasicStore.getData()}; }; 

    export default class AppCtrl extends AppCtrlRender { 
     constructor() { 
      super(); 
      this.state = getState(); 
      this.binder('storeDidChange', 'handleValueChange', 'handleRadioChange'); 
     } 

     componentDidMount() { 
      this.unsubscribe = BasicStore.listen(this.storeDidChange); 
     } 
     componentWillUnmount() { this.unsubscribe(); } 
     storeDidChange() { this.setState(getState()); } 
     handleRadioChange(event) { Actions.editRecord('type', event.target.value); } 
     handleValueChange(name, value) { Actions.editRecord(name, value); } 
    } 
1

Ich benutze Redux Staaten zu verwalten und mit redux-form Middleware-Formularfelder zu verwalten. Es speichert die Formularzustände im Stammzustand, sodass Sie einfach alle Werte auf einmal abrufen können.

Wenn Sie Redux nicht verwenden möchten, können Sie versuchen, this zu ändern, um jedes Eingabeelement in Ihrer Komponente automatisch zu verbinden, und einen Dekorierer wie this für Ihre Komponenten zu schreiben. Aber es ist schmutzig und ich empfehle es nicht.

+1

Haben Sie Beispiele oder Ausschnitte aus Ihrer Implementierung, die Sie gerne zeigen würden? Der Versuch, Redux- und React-Formen zu verstehen, war ein wenig schwindlig. : / –

Verwandte Themen