react使用antd表单

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

image.png

组件讲解:

<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如下:

image.png

其中详细讲解日期组件,
image.png

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

validateTrigger:校验子节点值的时机。disabledDate表示来确定不可选时段

image.png

红框中的日期是不可选择的。

/**
* 判断推荐时间是否选择
*/

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);

image.png

图上有将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);

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260