2017-05-18 84 views
-1

爲了學習目的,我正在用ReactJS編寫一個帶有嚮導的小應用程序。ReactJS簡單表單嚮導

我已經爲嚮導創建了一些組件,如下所示;

  • 進度
  • 嚮導
    • WizardStepOne
    • WizardStepOneForm
    • WizardStepTwo
    • WizardStepTwoForm

在嚮導組件中,我包含了用於顯示進度的PorgressBar組件,並創建了一個switch語句以確定每個「StepForm」中包含的按鈕的oneClick值,以獲取值並顯示下一個「WizardStepTwoForm」組件。

這一切運作良好,確實如我所料,但我面臨着一個問題。我不希望用戶在驗證'WizardStepOneForm'之前能夠獲得下一個'WizardStepTwoForm'表單。所以一些我應該如何返回一個狀態到我的父組件來確定用戶是否可以點擊到下一個狀態。或者,我通過一種狀態來禁用按鈕,直到驗證完成爲止,但在這種情況下,用戶將無法點擊按鈕來驗證表單。

在提交表單的過程中,我想將數據發送到API,調度工作正常,但我只是想知道如何解決這個問題,所以我的父語句(嚮導)中的switch語句只會被觸發if該表格是有效的。

嚮導

//.. imports 

class Wizard extends React.Component { 

    constructor(props) { 
     super(props); 
     this.state = { 
      step : 'stepOne', 
      progression : '0%' 
     }; 

     this.handleFormSubmit = this.handleFormSubmit.bind(this); 
    } 

    componentDidMount() { 
     const wizard = JSON.parse(localStorage.getItem('wizard')); 
     if (wizard !== null) { 
      this.setState({ 
       step: wizard.step, 
       progression: wizard.progression 
      }); 
     } 
    } 

    componentDidUpdate() { 
     localStorage.setItem('wizard', JSON.stringify({ 
      step  : this.state.step, 
      progression : this.state.progression 
     })); 
    } 

    handleFormSubmit(e) { 

     switch (e.target.value) { 
      case 'stepOne' : 
       this.setState({ 
        step : 'stepOne', 
        progression : '0%', 
       }); 
       break; 
      case 'stepTwo' : 
       this.setState({ 
        step : 'stepTwo', 
        progression : '50%' 
       }); 
       break; 
     } 
    } 

    /** 
    * 
    * Render 
    * @return {JSX} 
    */ 
    render() { 

     const { step, progression } = this.state; 

     switch (step) { 
      case 'stepOne' : 
       return (
        <div> 
         <Header /> 

          <WizardProgressBar progression={progression} stepOne="active" stepTwo="" /> 

          <WizardStepOne handleFormSubmit={this.handleFormSubmit} /> 

         <Footer/> 
        </div> 
       ); 
       break; 
      case 'stepTwo' : 
       return (
        <div> 
         <Header /> 

          <WizardProgressBar progression={progression} stepOne="done" stepTwo="active" /> 

          <WizardStepTwo handleFormSubmit={this.handleFormSubmit} /> 

         <Footer/> 
        </div> 
       ); 
       break; 
     } 
    } 
} 

export default Wizard; 

WizardStepOne

export default class WizardStepOne extends React.Component { 

constructor(props) { 
    super(props); 
} 

/** 
* 
* Render 
* @return {XML} 
*/ 
render() { 

    return(
     <div className="step-one"> 

      <h1>Step 1</h1> 

      <WizardStepOneForm handleFormSubmit={this.props.handleFormSubmit} /> 

     </div> 
    ); 
} 

}

WizardStepForm

//... imports 

@connect((store) => { 
    return { 

    }; 
}) 

export default class WizardStepOneForm extends React.Component { 

    constructor(props) { 
     super(props); 
     this.state = { 
      formData : { 
       firstName : '', 
       lastName : '', 
      }, 
      formErrors : { 
       firstName : true, 
       lastName : true, 
      }, 
      formErrorMessages : { 
       firstName : 'some validation message', 
       lastName : 'some validation message', 
      }, 
      formButtonEnabled : true, 
     } 

     this.handleSubmit   = this.handleSubmit.bind(this); 
     this.handleFirstNameChange = this.handleFirstNameChange.bind(this); 
     this.handleLastNameChange = this.handleLastNameChange.bind(this); 
    } 

    componentDidMount() { 
     const stepOne = JSON.parse(localStorage.getItem('stepOne')); 
     if (stepOne !== null) { 
      this.setState({ 
       formData : stepOne.formData, 
       formErrors : stepOne.formErrors, 
       formErrorMessages : stepOne.formErrorMessages, 
      }); 
     } 
    } 

    handleFirstNameChange(e) { 

     let formData   = this.state.formData; 
     let formErrors  = this.state.formErrors; 
     let formErrorMessages = this.state.formErrorMessages; 

     formData.firstName = e.target.value; 

     if (!e.target.value) { 
      formErrors.firstName = true; 
     } else { 
      formErrors.firstName = false; 
     } 
     this.setState({ formData : formData, formErrors : formErrors, formErrorMessages : formErrorMessages }); 
     localStorage.setItem('stepOne', JSON.stringify({ formData : formData, formErrors : formErrors, formErrorMessages : formErrorMessages })); 
    } 

    handleLastNameChange(e) { 

     let formData   = this.state.formData; 
     let formErrors  = this.state.formErrors; 
     let formErrorMessages = this.state.formErrorMessages; 

     formData.lastName  = e.target.value; 

     if (!e.target.value) { 
      formErrors.lastName = true; 
     } else { 
      formErrors.lastName = false; 
     } 
     this.setState({ formData : formData, formErrors : formErrors, formErrorMessages : formErrorMessages }); 
     localStorage.setItem('stepOne', JSON.stringify({ formData : formData, formErrors : formErrors, formErrorMessages : formErrorMessages })); 
    } 

    handleSubmitButton() { 

    } 

    handleSubmit(e) { 

     e.preventDefault(); 

     this.props.dispatch(addUser(this.state.formData)); 
    } 

    /** 
    * 
    * Render 
    * @return {XML} 
    */ 
    render() { 

     const firstNameError = this.state.formErrors.firstName ? 'error' : ''; 
     const lastNameError = this.state.formErrors.lastName ? 'error' : ''; 

     return(
      <form className="step-one-form"> 

       <div className="form-group right"> 

        <div className="form-group__form-row"> 

         <p className={classnames('col-2', firstNameError)}> 
          <label htmlFor="first_name">First name:</label> 
          <input type="text" id="firstName" name="fist_name" autoComplete="off" onChange={this.handleFirstNameChange} value={this.state.formData.firstName} /> 
          { firstNameError ? <FormElementErrorMessage message={this.state.formErrorMessages.firstName} /> : '' } 
         </p> 

         <p className={classnames('col-2', lastNameError)}> 
          <label htmlFor="last_name">Last name:</label> 
          <input type="text" id="lastName" name="last_name" autoComplete="off" onChange={this.handleLastNameChange} value={this.state.formData.lastName} /> 
          { lastNameError ? <FormElementErrorMessage message={this.state.formErrorMessages.lastName} /> : '' } 
         </p> 

        </div> 

       </div> 

       <button disabled={this.state.formButtonEnabled} onClick={this.props.handleFormSubmit} value="stepTwo">Next step</button> 

      </form> 
     ); 
    } 
} 
+0

你見過react-albus https://github.com/americanexpress/react-albus? –

+0

據我所知,我仍然會有相同的問題,因爲我的表單驗證將在WizardStepOneForm組件中完成 – directory

回答

0

所以,我發現它可能更容易,因爲我認爲。

表單提交處理程序出現在創建表單的子組件中。所以我們不需要從父母那裏推下來作爲道具。

由於我們將在表單'stepOne'有效時通過調度器觸發一個動作,我們通過減速器更改給定狀態。商店收到此狀態更改,該狀態更改已通過連接和應用程序根目錄中的提供程序追加,父組件將收到此狀態更改,我們可以啓動下一個嚮導屏幕。