如何在 React 中正确捕获 Materialize-CSS 日期选择器值?

IT技术 javascript reactjs datepicker materialize
2021-05-13 15:45:39

我希望在我的 React 组件中使用materialize-css创建一个带有日期选择器的表单我没有这个表单捕获的很多字段,并且结构相当简单。返回的表单如下所示:

<form onSubmit={this.handleSubmit.bind(this)}>
     <div className="container">
          <div className="card grey lighten-3">
               <div className="card-content black-text">
                    <span className="card-title">
                            <input placeholder="Event Name"
                                    name="name" value={this.state.name}
                                    onChange={this.handleStateChange.bind(this)}/>
                    </span>
                    <input name="description" placeholder="Description"
                                      value={this.state.description}
                                      onChange={this.handleStateChange.bind(this)}/>
                    <input name="image" placeholder="Image URL"
                                      value={this.state.image}
                                      onChange={this.handleStateChange.bind(this)}/>
                    <input placeholder="Start Date"
                                className="datepicker" name="startDate" value={this.state.startDate}
                                onSelect={this.handleStateChange.bind(this)}/>
                </div>
                <div class="card-action">
                    <div className="row">
                        <span>
                           <div className="col s3">
                               <input className="btn light-blue accent-1" type="submit" value="Submit"/>
                           </div>
                           <div className="col s3">
                               <a className="btn grey" onClick={this.handleExpand.bind(this)}>Cancel</a>
                           </div>
                       </span>
                   </div>
               </div>
           </div>
       </div>
   </form>

状态更改处理

handleStateChange(item) {
    this.setState({[item.target.name]: item.target.value});
}

我已经调用AutoInit来初始化我的日期选择器

M.AutoInit();

我尝试使用onChange而不是onSelect管理日期选择器状态更改,但它似乎没有捕获该事件。随着onSelect使用的日期有时会捕捉,如果我选择一个日期,然后重新打开日期选择器。

我还尝试使用一些替代的日期选择器初始化方法,但无济于事。

如何使用给定的设置正确捕获输入更改?

4个回答

嗨,希望这会帮助某人 -

<Da​​tePicker />组件发生的事情是默认的 onChange 方法返回日期 (2019-08-01) 而不是元素的事件处理程序对象。为了解决这个问题,我们需要在 onChange 方法中创建一个对象来模拟事件处理程序的 target.id 和 target.value

其他组件如<input />正常工作。看看这个:

组件应该是这样的:

            <DatePicker
                label="myDate"
                value={state.myDate}
                id="myDate"
                onChange={(newDate) => {
                    handleChange({
                        target: {
                            id: "myDate",
                            value: newDate
                        }
                    })
                }} />

这是完整的代码:

import React, { useState, useEffect } from "react";
import "materialize-css/dist/css/materialize.min.css";
import "materialize-css/dist/js/materialize.min.js";
import { DatePicker } from "react-materialize";

const PickDate = (props) => {

    const [state, setState] = useState({myName: "Mags", myDate: "2019-08-01"});

    const handleChange = (e) => {
        const key = e.target.id;
        const val = e.target.value;

        const newState = {...state};
        newState[key] = val;
        setState(newState);
    }

    return (
        <React.Fragment>
            <input type="text" value={state.myName} id="myName" onChange={handleChange} />
            <DatePicker
                label="myDate"
                value={state.myDate}
                id="myDate"
                onChange={(newDate) => {
                    handleChange({
                        target: {
                            id: "myDate",
                            value: newDate
                        }
                    })
                }} />
        </React.Fragment>
    );
}

export default PickDate;

附注。这使用 React Hooks - 但它也适用于普通类。

在研究了所有关于 React 生命周期的周六之后。我为此得到了这个解决方案:

组件的使用:

    <DatePicker label="Fecha" value={this.state.formSchedule.start} 
onChange={(date) => {
    this.state.formSchedule.start = date;
    this.setState({ formSchedule: this.state.formSchedule });
}}/>

类 DatePicker.tsx:

    import * as React from 'react';
import Materialize from 'materialize-css';
import moment from 'moment'
import 'moment/locale/es'
import { any } from 'prop-types';


interface IState {
  value: any;
}

interface IProps {
  label: any;
  format: any;
  onChange: any;
  formatMoment: any;
}

export default class DatePicker extends React.Component<IProps, IState> {

  static defaultProps = {
    label: "Fecha",
    value: new Date(),
    format: 'ddd d, mmm',
    formatMoment: 'ddd D, MMM'
  }

  constructor(props: any) {
    super(props);
    this.componentWillReceiveProps(props);
  }

  componentWillReceiveProps(props) {
    this.state = {
      value: props.value
    };
  }

  render() {
    return <div className="input-field col s6">
      <i className="material-icons prefix">date_range</i>
      <input id="date" type="text" className="datepicker queso"
        value={moment(this.state.value).locale('es').format(this.props.formatMoment)}
      />
      <label className="active" htmlFor="date">{this.props.label}</label>
    </div>;
  }


  componentDidMount() {
    var context = this;

    var elems = document.querySelectorAll('.queso');
    Materialize.Datepicker.init(elems, {
      defaultDate: new Date(),
      format: this.props.format,
      container: 'body',
      onSelect: function (date) {
        context.setState({ value: context.state.value });
        context.props.onChange(date);
      },
      autoClose: true
    } as Partial<any>);

  }
}

谢谢卢卡斯,你的回答也帮助了我。

这是我的解决方案 - 没有 redux 或 props,只有具有自己状态的类组件

import React, { Component } from "react";
import "./calendar.css";
import Materialize from "materialize-css";
import moment from "moment";

class Calendar extends Component {
  componentDidMount() {
    var context = this;

    var elems = document.querySelectorAll(".dateset");
    Materialize.Datepicker.init(elems, {
      defaultDate: new Date(),
      format: this.state.format,
      container: "body",
      onSelect: function(date) {
        context.setState({ value: context.state.value });
        console.log(date); // Selected date is logged
      },
      autoClose: true
    });
  }

  state = {
    value: new Date(),
    format: "ddd d, mmm",
    formatMoment: "ddd D, MMM"
  };

  render() {
    return (
      <div className="input-field col s6">
        <i className="material-icons prefix">date_range</i>
        <input
          id="date"
          type="text"
          className="datepicker dateset"
          defaultValue={moment(this.state.value).format(
            this.state.formatMoment
          )}
        />
      </div>
    );
  }
}

export default Calendar;

已经添加的答案都没有帮助我,所以我决定按照我的方式去做。我没有将 Materialize 和 jQuery 安装到我的module中,只是在 index.html 中添加了它们

当您单击输入字段时,日期选择器模式窗口将打开,并有两个按钮取消和确定。我找到了 jQuery 的 OK 按钮并添加了单击功能,该功能从输入字段中获取值并更新状态;

componentDidMount(){
window.$(".datepicker-done").click(() => {
      var datepickerValue = window.$("#date-input").val();  // date-input it's 'id' on datepicker input

      this.setState({ approxLastDay: datepickerValue });
    });
}

注意: datepickerValue 将采用字符串格式(例如“2019 年 8 月 6 日”)