13

I have a Materialize input like so:

<input type="date" className="datepicker" onChange={this.props.handleChange} />

It is being correctly initialised by Materialize, but not firing onChange when the value of the datepicker changes. What am I doing wrong here? This problem seems to extend to all Materialize inputs.

j_d
  • 2,818
  • 9
  • 50
  • 91
  • 1
    did u try binding this to the function if you are using ES6, ex: onChange={this.props.handleChange.bind(this)}; – Vikramaditya Jan 27 '16 at 12:51
  • @Vikramaditya Unfortunately I'm not using ES6, will try to find a commonjs way though. Thanks. – j_d Jan 27 '16 at 12:54
  • @Vikramaditya I get this error `React component methods may only be bound to the component instance`... – j_d Jan 27 '16 at 13:29
  • I am having the same issue. onChange is simply not triggering using Materialize for this datepicker. It works fine for the normal fields though, what am I missing? – born2gamble Nov 19 '18 at 08:43
  • Dear @j_d, please test the `onChange` with the following function, `onChange={function(e) { console.log(e.target.value)}}`, if it show the chosen date on the console so you should put the `handleChange` function inside your question. maybe the issue is from `handleChange` – AmerllicA Feb 26 '20 at 22:50
  • Dear @j_d, do you test my opinion? I just wanna help you. – AmerllicA Feb 27 '20 at 12:02
  • @j_d can you send ```handleChange``` function? Maybe your function not binded on constructor like ```this.handleChange = this.handleChange.bind(this)```? Or if you use arrow function: ```const handleChange = (value) => {}```. According your error somewhere you don't binded your function. – aturan23 Feb 29 '20 at 06:27
  • You should provide the code to show how the `handleChange` implemented and passed to your component. IMHO, your problem is irrelevant to `Material` as well. – thelonglqd Dec 31 '20 at 07:25

7 Answers7

1

On componentDidUpdate() using a prop id

var elem = document.getElementById('date');
        M.Datepicker.init(elem,{
            onClose:()=>{
                this.state.date = elem.value;                    
                this.setState(this.state)
            }
        });
0

I'm pretty sure this solves the caveat if you put it in your componentDidMount component. If the select is to be re-rendered on state change, this should as well be put in componentDidUpdate

// find the select element by its ref
const el = ReactDOM.findDOMNode(this.refs.ref_to_my_select);
// initialize the select
$('select').material_select();
// register a method to fireup whenever the select changes
$(el).on('change', this.handleInputChange)
Adil Saiyad
  • 1,582
  • 2
  • 17
  • 34
0

To get the value of the datepicker in materialize they provide an onSelect option when initialising the component:

var instances = M.Datepicker.init(
      elems,
      {
        onSelect:function(){
          date = instances[0].date;
          console.log(date);
        }
      }
    );

https://codepen.io/doughballs/pen/dyopgpa

Every time you pick a date, onSelect fires, in this case console.logging the chosen date.

When you close the datepicker (which is actually a modal), that's when the onChange fires, in this case logging 'onChange triggered' to the console.

Sean Doherty
  • 2,273
  • 1
  • 13
  • 20
0

that's my solution. I use useRef hook, to identify datepicker input and when onClose is fired, we can capture the object and data value, through ref var.

import React, { useEffect, useState, useRef } from "react";
import M from "materialize-css";

export default function App() {

  const fromref = useRef(null); //create reference

  const [date, setDate] = useState({ fromdate: "" });

  const { fromdate } = date;

  useEffect(() => {
    let elem = document.querySelectorAll(".datepicker");
    M.Datepicker.init(elem, {
      firstDay: true,
      format: "yyyy-mm-dd",
      onClose: function() { // when onclose datepicker, we can get the value and data through the ref
        console.log(fromref.current.name, fromref.current.value);
        setDate({ [fromref.current.name]: fromref.current.value });
      }
    });
  }, []);

  return (
    <form class="col s12">
      <div class="row">
        <div class="input-field col s12">
          <input
            name="fromdate"
            type="text"
            class="datepicker"
            placeholder="from date"
            ref={fromref} //set reference to the input
          />
        </div>
      </div>
    </form>
  );
}
AAlvarez
  • 1
  • 2
0

If you want to get the value or other attributes you can access them from instaces variable when initialized and then check before submitting your form.

var elems = document.querySelectorAll('.timepicker');
var instances = M.Timepicker.init(elems);

Then in order to get your value before submitting your form can do as follow:

var date = instances[0].el.value;
Philipos D.
  • 2,036
  • 1
  • 26
  • 33
-1

There are two things which might be stopping the execution of expected behaviour.


  1. If the code which you have displayed question section is from rendered html tree, then onchnage assigment needs to be called while assignment itself.
<input type="date" className="datepicker" onChange=this.props.handleChange(event)/>
  • Note: Previously browser events use to expects event callback handlers in string format as a value.


-2

It looks like you're using materialize directly in your post but if it is possible, you could try using react-materialize as it wraps all the materialize components such that it's easier to use with React. Using react-materialize would probably be the cleanest way to handle state and event changes as they provide a convenience wrapper around each materialize component.

When using the date picker from react-materialize, you'll need to pass the handleChange method into the options prop like so:

<DatePicker
  options={{
    ...,
    onSelect: this.props.handleChange
  }}
 />

In the case of using the materialize date picker independently, if you could provide more details on how you're initializing the date picker input, I could provide a more relevant answer. But I'll give it a shot in the dark.

From the materialize docs it looks like you'll also have to pass back some options when you initialize it to handle a callback function when a date is selected.

I've added a JSFiddle that has a working example as well as a code snippet below, notice that when you select a date, 'hello world' is logged in the console, and the date is the first argument passed into the callback.

class Datepicker extends React.Component {
  constructor(props) {
    super(props)
  }

  handleChange(date) {
    console.log('hello world', date);
  }

  componentDidMount() {
      var elems = document.querySelectorAll('.datepicker');
      var instances = M.Datepicker.init(elems, {
        onSelect: this.handleChange
      });
  }

  render() {
    return (
        <div>
          <input type="text" className="datepicker" />
        </div>
    )
  }
}

Live Example Fiddle

So to answer your question of how to handle events and setting the state, you just need to pass your handleChange method into the provided options configs depending on how you're using materialize date picker. In regards to integrating with a form, you could use the other callback hooks like onClose to do form validation.

Sherman Hui
  • 938
  • 3
  • 10
  • 22