【问题标题】:How do I correctly capture Materialize-CSS datepicker value in React?如何在 React 中正确捕获 Materialize-CSS datepicker 值?
【发布时间】:2019-05-19 10:26:52
【问题描述】:

我希望在我的 React 组件中使用 materialize-css 创建一个带有 datepicker 的表单。这个表单捕获的字段不多,结构相当简单。返回的表单如下所示:

<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,如果我选择一个日期然后重新打开日期选择器,有时会捕获日期。

我也尝试过使用一些alternate initialization methods for the datepicker 无济于事。

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

【问题讨论】:

  • 不相信有onSelect - 你的意思是onChange 吗?
  • 我已经尝试了几个星期,但一切都是徒劳的,即使我想知道它的答案。
  • @SakoBu 我在问题中提到了这一点。似乎都没有提供所需的行为
  • 哦,我也有同样的问题...这真的很难...对于时间选择器,我可以使用 onBlur 来完成...但不能使用 datepicker
  • Check this repository in this 我尝试制作 Materialize CSS 提供的所有 Javascript 组件 - github.com/GermaVinsmoke/Reactize

标签: javascript reactjs datepicker materialize


【解决方案1】:

您好,希望这会对某人有所帮助 -

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

等其他组件正常工作。看看吧:

这是组件的外观:

            <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 - 但它也适用于普通类。

【讨论】:

    【解决方案2】:

    在研究了所有关于 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>);
    
      }
    }
    

    【讨论】:

    • 伙计,这在 react 和 redux 的情况下也很有效。谢谢
    【解决方案3】:

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

    这是我的解决方案 - 没有 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;
    

    【讨论】:

      【解决方案4】:

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

      当您单击输入字段时,日期选择器模式窗口将打开,并且有两个按钮 CANCEL 和 OK。我通过 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 将采用字符串格式(例如“Aug 6, 2019”)

      【讨论】:

        【解决方案5】:

        我有同样的问题,这是我的解决方案。

        import React, { Component } from 'react'
        import M from 'materialize-css';
        
        class CreateReport extends Component {
            constructor(props) {
                super(props);
                this.state = {
                    startDate: '',
                    endDate: ''
                };
                // refs for startDate, endDate
                this.startDate = React.createRef();
                this.endDate = React.createRef();
            }
            componentDidMount() {
                var context = this;
                document.addEventListener('DOMContentLoaded', function () {
                    var start = document.querySelectorAll('.datepicker');
                    M.Datepicker.init(start, {
                        format: "mm/dd/yyyy",
                        autoClose: true,
                        onClose: context.handleDate
                    });
                });
            }
            handleDate = () => {
                this.setState({
                    startDate: this.startDate.current.value,
                    endDate: this.endDate.current.value,
                })
                // console.log(this.state.startDate)
                // console.log(this.state.endDate)
            }
            handleChange = (e) => {
                this.setState({
                    [e.target.id]: e.target.value
                })
            }
            handleSumbit = (e) => {
                e.preventDefault();
                console.log(this.state)
            }
            render() {
                return (
                    <div>
                        <div className="container">
                            <form onSubmit={this.handleSumbit} className="white col s12 m6">
        
                                <div className="row">
                                    <div className="input-field col s3 offset-s2">
                                        <label htmlFor="date">Start Date</label>
                                        <input
                                            type="text"
                                            className="datepicker"
                                            id="startDate"
                                            onChange={this.handleChange}
                                            value={this.state.startDate}
                                            ref={this.startDate}
                                        />
                                    </div>
                                    <div className="input-field col s3 offset-s2">
                                        <label htmlFor="date">End Date</label>
                                        <input
                                            type="text"
                                            className="datepicker"
                                            id="endDate"
                                            onChange={this.handleChange}
                                            value={this.state.endDate}
                                            ref={this.endDate} />
                                    </div>
                                </div>
                                <div className="col s8 offset-s2 center-align">
                                    <button className="btn pink lighten-1 z-depth-0 ">Sign Up</button>
                                </div>
        
                            </form>
                        </div>
                    </div >
                )
            }
        }
        export default CreateReport
        

        【讨论】:

          【解决方案6】:

          我做了一个不太优雅的解决方案,但它也有不少代码行。它似乎正在工作(经过数小时的调试!)。

          我创建了一个名为 trouble 的 css 类,并将其应用于处理 DatePickerTimePicker 的所有字段。在初始化中,我创建了事件监听器来检查更改。当检测到更改时,它会调用 _valueTracker,并使其发送 redux 注意到的更新事件。

          一件非常奇怪的事情是,如果我传入与 e.target.value 完全相同的值,它什么也不做。它必须是一串随机的东西,例如“UPDATE!”在这种情况下。我将此代码与物化初始化的其余部分一起使用。

          const troubles = document.querySelectorAll(".trouble");
          troubles.forEach((item) => {
            item.addEventListener("change", (e) => {
              e.target._valueTracker.setValue("UPDATE!");
            });
          });
          

          【讨论】:

          • 顺便说一句:这有点像 hack,但它节省了我重写所有不同的日期和时间组件,这很简单。
          猜你喜欢
          • 2016-05-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多