如何解決antd組件動態添加表單控件無法覆蓋默認值問題

問題

由於項目需要實現一個爲經銷商添加管理員的功能。如下圖所示:
在這裏插入圖片描述
要求:

  • 至少添加一個管理員賬號
  • 需要對管理員手機號做格式校驗,非空校驗,去重校驗;管理員姓名做非空校驗
  • 能夠動態刪除和添加管理員,並且格式化數據表單提交

實現

看到這裏我們立馬能夠想到在通過數據實現,react語言的特殊性,通過數據反映dom的變化,所以對數據元素的添加和刪除能夠反映的dom元素。好了,原理知道了。接下來上代碼
首先數據結構選擇,數組的元素的數據結構如下:

constructor(props) {
    super(props);
    this.state = {
      managerList: [{name: "", phone: ""}],
    };
  }

然後在render方法中構造一個組件數組,如下。

render() {
	....
	let {managerList} = this.state;
    let managerNumber = managerList.length;
	let managerComps = managerList.map((el, index) =>{
      return (
        <span key={index}>
          <Row span={24}>
            <Col span={8}>
              <FormItem label="管理員姓名:" labelCol={{span: 10}} wrapperCol={{span: 12}}>
                  {getFieldDecorator(`name${index}`,{
                    initialValue: el.name,
                    rules: [{
                      required: true,
                      message: '請填寫管理員姓名'
                    }]
                  })(
                    <Input />
                  )}
             </FormItem>
            </Col>
            <Col span={8}>
              <FormItem label="管理員手機號:" labelCol={{span: 8}} wrapperCol={{span: 12}}>
                  {getFieldDecorator(`phone${index}`,{
                    initialValue: el.phone,
                    rules: [{
                      required: true,
                      message: '請填寫管理員手機號'
                    },{
                      pattern: /^1[3|4|5|7|8][0-9]\d{8}$/, message: '請輸入正確的手機號'
                    },{
                      validator:this.phoneDuplicateValidator,
                    }],
                  })(
                    <Input />
                  )}
             </FormItem>
            </Col>
            <Col span={4} style={{marginTop:6}}>
             {index === 0 && managerNumber < 5 && <Button shape="circle" size="small" icon="plus" type="primary" style={{marginRight:10}} onClick={() => this.addManager()} />}
             {((managerNumber > 1 && index === 0) || index > 0)  && <Button shape="circle" size="small" icon="minus" type="default" onClick={() => this.delManager(index)} />}
           </Col>
           </Row>
        </span>
      )
    });

	return(
	<Form >
		<div className="ant-descriptions-title">
             管理員賬號
       </div>
       <div>
         <div>
           {managerComps}
         </div>
       </div>
    </Form>   
	)
}

新增元素對應的addManager方法

  collectManager = () =>{
    const {getFieldValue, resetFields} = this.props.form;
    const managerList = [];
    let managerNumber = this.state.managerList.length;
    for (let i = 0; i < managerNumber; i++){
      let name = getFieldValue(`name${i}`);
      let phone = getFieldValue(`phone${i}`);
      //!!!!重要,如果不加此方法,則會在刪除元素時,getFieldDecorator的initalValue屬性不生效的問題
      resetFields([`name${i}`,`phone${i}`]);
      managerList.push({name: name, phone: phone});
    }
    return managerList;
  }
  
  addManager = () =>{
    let managerList = this.collectManager();
    managerList.push({name: "", phone: ""});
    this.setState({managerList});
  }

刪除元素對應的delManager方法

 delManager = (index) =>{
    let managerList = this.collectManager();
    //刪除指定index的元素
    managerList.splice(index,1);
    this.setState({managerList});
  }

元素去重校驗方法

phoneDuplicateValidator = (rule, value, callback) =>{
    const {getFieldValue} = this.props.form;
    let managerNumber = this.state.managerList.length;
    let count = 0;
    for (let i = 0; i < managerNumber; i++){
      let phone = getFieldValue(`phone${i}`);
      if(phone === value){
        count++;
      }
    }
    count > 1 ? callback('管理員手機號碼不能重複') : callback();
  }

實現後的效果自己可以本地看一下,之所以要寫這篇博客,是因爲我在實現的過程中遇到了刪除元素了initialValue屬性不生效的問題。導致的結果就是每次都是刪除最後一個元素(因爲數組長度減一了)
爲了解決這個問題我嘗試了很多種方法,比如:
1.設置一個visible屬性,每次刪除後重新掛載數組元素
2.手動調用form組件的setFieldsValue設置值。

以上方法嘗試後全部失敗了。由於我就想是什麼原因導致了這個問題,仔細查看antd官方文檔。發現了resetFields這一段描述
在這裏插入圖片描述
然後我便嘗試在每次操作時,重置控件的值。此問題隨即解決了。

總結

當我們使用getFieldDecorator並用initialValue設定初始值時,當我們改變組件的值時,組件表現出的值也改變了,但這個值並不是initialValue設定的,其是組件內部的state值保持的,如果需要繼續用initialValue來設定組件的值,我們需要調用resetFields方法使initialValue有效。

前端路漫漫,作爲一個後端開發工程師,寫前端感覺更難,大家互勉!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章