2019-11-20 20:39:25 justDoItfl 阅读数 1092

一、情形

      最近在处理react 页面的时候遇到了一个问题:使用ant 的table组件,里面的可编辑单元格类型,但是 我的数据 有一个下拉框在表格中,因为可编辑的table 组件默认单元格是 input输入框,所以下拉框根本就拿不到值,显示不上。

 先说一下 下拉框 在表格 column 的写法:

{
                title: '数据来源',
                dataIndex: 'dataSource',
                key: 'dataSource',
                render: (text, record, idx) => {
                    return (

                            <Select
                                style={{ width: 200 }}
                                id="dataSource"
                                onChange={this.changeSource.bind(text,record,idx)}
                                value={record.dataSource}
                            >
                                {this.state.itemsValue.map(item => (
                                    <Option key={item.seKey}>{item.seValue}</Option>
                                ))}

                            </Select>

                    )
                },
                width: 300,
                editable: false
},

主要是reade 的写法,官方api上上这么描述的,

 render            Function(text, record, index) {}

生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格行/列合并
代码中: this.state.itemsValue 是下拉框的所有数据,value  是 下次进入页面需要 回显的值,为了这个回显的值,我忙活了近倆小时。

二、解决得问题

第一个问题:下拉框的回显

因为要回显的数据 在arry<Object> 里,而且有childern 项,我先想着怎么循环拿出来,赋给value,但是均未成功,最后灵光一现。我发现了问题的所在,每条数据在table显示的时候已经循环过了,问题就在我能不能拿到当前行的数据, 能拿到就能拿到当前改下拉框的值,翻一翻api 就什么都有了。record 就是当前的数据对象,直接点 属性就是值。

第二个问题:

下拉框选中值后如何在 可编辑的表格上显示:

官方的可编辑单元格的保存你输入的数据到表格的方法是这样的:

handleSave = row => {
    const newData = [...this.state.dataSource];
    const index = newData.findIndex(item => row.key === item.key);
    const item = newData[index];
    newData.splice(index, 1, {
      ...item,
      ...row,
    });
    this.setState({ dataSource: newData });
  };

其中,row是你输入数据的那行数据,newData 是表格中所有数据,数组.findIndex ( =()=>{ }) 方法是当其中匿名箭头函数的方法返回true 的时候返回已选数据在 newData数组的下标,(如果没找到返回的-1),

拿到对应下标后,删除源数据newData下标的数据,然后把row加进来,也就是用已经改变的row替换之前数据的item,也就是splice ()方法的作用,

3个参数分别是index,要删除/添加的下标,1,删除的个数,{} 在下标位置增加的数据、

最后把修完的数据返回state,页面重新渲染,把数据显示在表格上。(每改一次,触发onChange事件,渲染一次。。。)

这个方法对于输入框 是一点问题没有,但是下拉框就不行了,因为row对象拿不到你选得数据,input是value属性,但是下拉框是option 标签,所以即便你怎么选下拉框一直是空。怎么办,勤劳的人总会有收获,这时我想到 @wslzjr 帅帅博主对我的鼓励:

我感觉瞬间充满了力量,没什么是加班解决不了的,如果有,那就班加的不够。 我的想法是这样的,对于下拉框,我自己拿值,自己替换数据,然后让页面重新渲染,不走官方的方法不就行了。于是我自己写了一套,

 changeSource =(t,e,r) =>{
        //设置数据的值,用this.setState({})
        let row = t;
        const {
            fieldName,
            fieldDesc,
            dataType,
            fieldLength,
            dataSource,
            fieldValue,
            required,
            validRule

        } = row;
        row.dataSource=r;
        let { rootNodesMap } = this.state;
        Object.assign(rootNodesMap[row.id], row);
        this.setState({ rootNodes: this.state.rootNodes });
        this.updateDataSource(this.state.rootNodes);
    }

 其中,t 是当前的哪行数据 ,e 当前行数据,r,行索引,  assign 是对象属性的同级拷贝方法,他无法深层次拷贝,但是我够用了。Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。  这样表格的下拉框就有数据了。

   总结:帅帅博主真的厉害!

 

 

 

2019-10-20 21:43:26 zhenzheni 阅读数 1017

antd的select组件(模糊查询,远程加载)在表单页设置默认值进行回显

需要回显成这样:(正确)

select:name

实际上回显成:(错误)

select:id

设置initialValue: id,则页面上是显示id

实际上应该显示name

但如果设置initialValue: name,则页面一旦进行再次提交且这个select没有进行重新选择 传给后端的就不再是id而是name

解决方法:

id转为字符串

原因:因为使用的antd的版本的原因 使用的版本并不支持number数据类型导致的

2020-04-18 16:26:24 qq_21901233 阅读数 62

最近在逐渐将函数写法从class组建从函数组件转变,在开发的过程中遇到了一个表单中的小问题,这里记录一下:

场景:页面有两个下拉框,有联动关系,第二个下拉框需要根据第一个下拉框的值发生变化,所以在第一个下拉框的onChange的回调函数中完成数据获取之后,需要调用form.setFieldsValue将第二个下拉框中的值更新掉,但是hooks插件会提示你缺少了一个form依赖项,当把form依赖项添加到依赖数组中之后,页面就会陷入死循环中,因为函数中对form表单的某一项做了赋值操作,而依赖项中有form,这样就造成了无限循环。但是如果不填的话又感觉不太好,总想找一个办法来解决这个问题。

一种暴力的解决方法就是直接使用vscode的提示,在对应行上面加一行eslint注释,使得页面不提示缺少了依赖项

我这边找到的另外一种解决方法是把setFieldsValue这个函数作为依赖项传入到依赖数组中,而不是把form传入进去,从github上有关的问题来看也推荐使用这种办法来解决这个问题,form作为依赖项传入进去是一定会出问题的。

2016-11-07 18:56:00 weixin_30657999 阅读数 0

引用form是第三方插件ant插件,官网网址:https://ant.design/。用到的antd的版本是@2.0.1。form(https://ant.design/components/form/)表单页面的大概样子如下:



组件讲解:

<Form></Form>表单horizontal表示水平排列布局,数据类型是布尔,默认值为false;onSubmit表示数据验证成功后回调事件,数据类型是函;required表示必填,前面会显示红色的图标。

<FormItem></FormItem>中包含的是一个小小的组件,可以是文本框、单选按钮、多选按钮、下拉框等。{...formItemLayout}是reactjs中属性的写法{...props},formItemLayout标签布局,wrapperCol需要为输入控件设置布局样式时,和label 标签布局,通 <Col> 组件,设置 span offset 值,如{span: 3, offset: 12}。label标签的文本。getFieldDecorator用于和表单进行双向绑定,获取该组件的值:this.props.form.getFieldDecorator(id, options)。详细API如下:

其中详细讲解日期组件,代码如下,getFieldDecorator中的id是timeRange,是form中唯一的;initialValue日期初始化的值,类型是[moment,moment],moment(startDate).startOf('day')是将今天的日期转换为日期组件所能显示的格式;rules表示校验,数据类型是数组【】。若是没选择日期提交form表单时,会在日期组件输出“请输入时间段!",dateSelect方法是在提交的时候调用进行相对应的校验,更多校验请点击该网址:https://github.com/yiminghe/async-validatorvalidateTrigger:校验子节点值的时机。disabledDate表示来确定不可选时段红框中的日期是不可选择的。

 /**
     * 判断推荐时间是否选择
     */
    dateSelect(rule, value, callback) {
        if(!this.state.disabledDates){
            if(value===undefined){
                callback(new Error("请输入时间段!"));
            }else{
                callback();
            }
        }else if(this.state.disabledDates){
            callback();
        }
    }

//设置日期组件所选择的日期(所选择的日期只能是今天及今天以后的)
        const disabledDate = function (current) {
           return  current  <= (new Date()).getTime()-1000*60*60*24;
        };

const date = new Date();
const startDate=date.toLocaleDateString();//获取当前日期(年月日)

<FormItem wrapperCol={{span: 16, offset: 2}}>
       {getFieldDecorator('timeRange',
           {initialValue:[moment(startDate).startOf('day'),moment(startDate).endOf('day')]},
          {rules: [{validator: this.dateSelect.bind(this)},],},
         {validateTrigger:'onChange'})
        (<RangePicker disabled={this.state.disabledDates} disabledDate={disabledDate} />)}
</FormItem>

当form中的FormItem组件创建完毕,需要定义组件默认的属性值以及校验从父组件传递的属性,最后再将form表单包起来。代码如下:

//定义组件默认的属性值(如果父组见没有传递数据,使用默认数据)
CreateActivity.defaultProps = {};
//校验从父组件传递的属性值是否符合
CreateActivity.propTypes = {
    createDatas: React.PropTypes.object,
    createActions: React.PropTypes.object.isRequired
};
//将CreateActivity通过Form.create()包装起来
export default CreateActivity = Form.create()(CreateActivity);

图上有将form表单回显的方法:mapPropsToFields,类型是一个方法:Function(props): Object{ fieldName: Object{ value } }

例如以上日期的回显方法如下:

function mapPropsToFields(props) {
    if (props.editDatas.queryAtyDatas.atyQuerySuccess == 'yes') {
        var formData = props.editDatas.queryAtyDatas.ReturnDatas.data;
        //修改活动初始化操作
        return {
            "timeRange": {value: [moment(formData.startDate).startOf('day'), moment(formData.endDate).endOf('day')]}
        };
    }
}
//将初始化表单的方法mapPropsToFields包裹到EditActivity组件中
export default EditActivity = Form.create({
    mapPropsToFields: mapPropsToFields
})(EditActivity);

 

以上创建和修改就完成了。详细代码如下:

import {Row, Col, Select, Form, Input, Button, Checkbox, Radio, Tooltip, Icon,DatePicker} from 'antd';
import {Router, Route, browserHistory, hashHistory, IndexLink, Link} from 'react-router';
import React, {Component, PropTypes} from 'react'
import OperpConfig from './OperpConfig';

import css from '../css/activity.css';
import '../../../common/sass/operp/operp.scss';
var moment=require('moment');

const FormItem = Form.Item;
const RadioGroup = Radio.Group;
const RangePicker = DatePicker.RangePicker;

class CreateActivity extends React.Component {
    constructor(props) {
        super(props);
        //取消
        this.handleCancel = this.handleCancel.bind(this);
        //提交订单
        this.handleSubmit = this.handleSubmit.bind(this);
        //审批
        this.handleApprove = this.handleApprove.bind(this);
    }
    /*生命周期函数--->该方法在完成首次渲染之前被调用*/
    componentWillMount() {
        /* 设置推荐时段的状态*/
        this.setState({
            disabledDates: false
        });
    }
    /*首次使用组建类时,组件已经被渲染,DOM操作请放在这*/
    componentDidMount() {
        let editDefaultformData = this.props.form.getFieldsValue();
    }

    /*存在期:随着应用状态的改变,以及组件逐渐受到影响,你将会看到下面的方法一次被调用:*/
    componentWillReceiveProps(nextProps) {
        let formData = this.props.form.getFieldsValue();
        /*当formData.timeFlag-1,代表不限时段,日期组件即将不可用,1是限时段日期组件可以选用*/
        if (formData.timeFlag === '-1') {
            this.props.form.resetFields([['timeRange']]);
            this.setState({
                disabledDates: true
            });
        } else {
            this.setState({
                disabledDates: false
            });
        }

    }

    /**
     *条件:当组件确定要更新,在 render 之前调用
     *用处:这个时候可以确定一定会更新组件,可以执行更新前的操作
     *注意:方法中不能使用 setState ,setState 的操作应该在 componentWillReceiveProps 方法中调用
     * @param nextProps
     * @param nextState
     */
    componentWillUpdate(nextProps, nextState) {
    }

    /**
     * 组件已经被更新后的方法
     * @param nextProps
     * @param nextState
     */
    componentDidUpdate(nextProps, nextState) {
        /*创建活动成功后跳转活动主界面*/
        if (this.props.createDatas.submitDatas.createSubmitSuccess == 'yes') {
            browserHistory.push('/activity');
        }
    }
    

    handleSubmit(e) {
        e.preventDefault();
        this.props.form.validateFields((errors, values) => {
            if (errors) {
                console.log('Errors in form!!!');
                return;
            }
            //所有的form表单值,等同于values
            const formData = this.props.form.getFieldsValue();
            //从表单中获取日期timeRange的值(起始时间+结束时间)是个数组
            const timeRange = formData['timeRange'];
             /*若是不限时段 日期数组就为null*/
            if(timeRange===undefined || formData['timeFlag']==='-1'){
                formData.startDate=null;
                formData.endDate=null;
            }else if(timeRange!==undefined && formData['timeFlag']==='1'){
                //格式化时间数组为YYYYMMDD  startDate:起始时间 endDate:结束时间          
                formData.startDate=timeRange[0].format('YYYYMMDD');
                formData.endDate=timeRange[1].format('YYYYMMDD');
            }
            //默认添加创建人
            formData.createUser = '创建人1';
            this.props.createActions.createActivity(formData);
        });
    }

     /**
     * 判断推荐时间是否选择
     */
    dateSelect(rule, value, callback) {
        if(!this.state.disabledDates){
            if(value===undefined){
                callback(new Error("请输入时间段!"));
            }else{
                callback();
            }
        }else if(this.state.disabledDates){
            callback();
        }
    }

    /**
     * 取消跳转到活动主界面
     */
    handleCancel() {
        console.log('取消跳转');
        browserHistory.push('/activity');
    }
    /**
     * 提交审批
     */
     handleApprove(e){
        alert('提交审批');
        console.log('提交审批');
     }
    render() {
        const {getFieldDecorator, getFieldError, isFieldValidating} = this.props.form;
        const formItemLayout = { labelCol: {span: 2}, wrapperCol: {span: 10},};
        //设置日期组件所选择的日期(所选择的日期只能是今天及今天以后的)
        const disabledDate = function (current) {
           return  current  <= (new Date()).getTime()-1000*60*60*24;
        };
        const date = new Date();
        const startDate=date.toLocaleDateString();
        const endDate = date.toLocaleDateString()+1;
        return (
            <div>
                <Row>
                    <Col span={24}>
                        <h1>新增推荐活动</h1>
                    </Col>
                </Row>
                <Row >
                    <Col span={24}>
                        <div className="edit-underline"></div>
                    </Col>
                </Row>
                <div className="text_dom">
                    <span className="span_text"><Icon type="exclamation-circle-o" className="icon_css"/>
                    设置完成后,系统自动对同一运营位不同位置输出内容去重。
                    </span>
                </div>
                <Form horizontal onSubmit={this.handleSubmit}>
                    <FormItem
                        {...formItemLayout}
                        label="活动名称"
                        required
                    >
                        {getFieldDecorator('activityName', {
                            rules: [
                                {required: true,
                                  message: '活动名称不能为空!'},
                            ],

                        })(
                            <Input type="text" placeholder="请输入活动名称..."/>
                        )}
                    </FormItem>
                    <FormItem
                        {...formItemLayout}
                        label="活动类型"
                    >
                        {getFieldDecorator('activityType', {initialValue: '1'})(
                            <RadioGroup>
                                <Radio value="1">正式运营</Radio>
                                <Radio value="2">A/B测试</Radio>
                            </RadioGroup>
                        )}
                    </FormItem>
                     <FormItem
                        {...formItemLayout}
                        label="推荐时段"
                    >
                        {getFieldDecorator('timeFlag', {initialValue: '1'})(
                            <RadioGroup>
                                <Radio value="1">限时段&nbsp;&nbsp;&nbsp;</Radio>
                                <Radio value="-1">不限时段</Radio>
                            </RadioGroup>
                        )}
                    </FormItem>
                     <FormItem wrapperCol={{span: 16, offset: 2}}>
                      {getFieldDecorator('timeRange',
                            {initialValue:[moment(startDate).startOf('day'),moment(startDate).endOf('day')]},
                            {rules: [{validator: this.dateSelect.bind(this)},],},
                            {validateTrigger:'onChange'})
                      (<RangePicker disabled={this.state.disabledDates} disabledDate={disabledDate} />)}
                    </FormItem>
                    <FormItem {...formItemLayout} label="备注">
                        {getFieldDecorator('comments')(<Input type="textarea" />)}
                    </FormItem>
                    <FormItem wrapperCol={{span: 16, offset: 2}} style={{marginTop: 24}}>
                        <Button type="primary" htmlType="submit">保存</Button>
                        &nbsp;&nbsp;&nbsp;
                        <Button type="primary" onClick={this.handleApprove.bind(this)}>提交审批
                        </Button>
                        &nbsp;&nbsp;&nbsp;
                        <Button type="ghost" onClick={this.handleCancel}>取消</Button>
                    </FormItem>
                </Form>
            </div>
        )
            ;
    }
}
//定义组件默认的属性值(如果父组见没有传递数据,使用默认数据)
CreateActivity.defaultProps = {};
//校验从父组件传递的属性值是否符合
CreateActivity.propTypes = {
    createDatas: React.PropTypes.object,
    createActions: React.PropTypes.object.isRequired
};

export default CreateActivity = Form.create()(CreateActivity);

 

转载于:https://www.cnblogs.com/qinbb/p/6040096.html

2019-07-01 13:57:00 weixin_33750452 阅读数 166

element的DatePicker获取value的时候是日期对象如下,可以提交的时候查看参数

 

2019-06-30T17:02:02.000Z 

如果是console.log打印出来的话,是这样的

查看了下,后台接收的时间也是这样的,所以就无需转时间戳或字符串('2019-07-01 11:42:58')了.

问题,如何在DatePicker中回显时间

应用场景:编辑

解决方案:

      new Date('2019-06-30T17:02:02.000Z')或new Date('2019-07-01 11:42:58')即可

转载于:https://www.cnblogs.com/wang715100018066/p/11113658.html