Je cherche à créer un formulaire avec un datepicker dans mon React avec materialize-css . Je n'ai pas beaucoup de champs ce le formulaire est en train de capturer et la structure est assez simple. Le formulaire retourné ressemble à ceci:
<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>
Le changement d'état est géré avec
handleStateChange(item) {
this.setState({[item.target.name]: item.target.value});
}
et j'ai appelé le AutoInit pour initialiser mon datepicker
M.AutoInit();
J'ai essayé d'utiliser onChange
au lieu de onSelect
pour gérer le changement d'état du sélecteur de date, mais il ne semble pas capturer cet événement. Avec onSelect
utilisé, la date est parfois capturée si je choisis une date puis rouvre le sélecteur de dates.
J'ai également essayé d'utiliser certains des méthodes d'initialisation alternatives pour le sélecteur de date en vain.
Comment capturer correctement le changement d'entrée avec ma configuration donnée?
Salut, j'espère que cela aidera quelqu'un -
Ce qui se passe avec le composant <DatePicker /> est que la méthode onChange par défaut renvoie la date (2019-08-01) et non l'objet gestionnaire d'événements de l'élément. Afin de contrer cela, nous devons créer un objet à l'intérieur de la méthode onChange qui imite les target.id et target.value du gestionnaire d'événements.
D'autres composants comme <input /> fonctionnent comme d'habitude. Vérifiez-le:
Voici à quoi devrait ressembler le composant:
<DatePicker
label="myDate"
value={state.myDate}
id="myDate"
onChange={(newDate) => {
handleChange({
target: {
id: "myDate",
value: newDate
}
})
}} />
Voici le code complet:
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;
PS. cela utilise React Hooks - mais cela fonctionnera aussi sur les classes normales.
Merci Lucas, ta réponse m'a aussi aidé.
Voici ma solution -sans redux ou accessoires, juste le composant de classe avec son propre état
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;
Aucune des réponses déjà ajoutées ne m'a aidé, alors j'ai décidé de le faire à ma façon. Je n'ai pas installé Materialise et jQuery dans mes modules, je les ai juste ajoutés dans index.html
Lorsque vous cliquez sur le champ de saisie, la fenêtre modale datepicker s'ouvre et il y a deux boutons CANCEL et OK. Je trouve ce bouton OK par jQuery et ajoute une fonction de clic, qui prend la valeur du champ de saisie et met à jour l'état;
componentDidMount(){
window.$(".datepicker-done").click(() => {
var datepickerValue = window.$("#date-input").val(); // date-input it's 'id' on datepicker input
this.setState({ approxLastDay: datepickerValue });
});
}
REMARQUE: datepickerValue sera au format chaîne (par exemple, "6 août 2019")
J'ai le même problème, voici ma solution.
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
Après avoir étudié tout le samedi sur le cycle de vie de React. J'ai obtenu cette solution pour cela:
L'utilisation du composant:
<DatePicker label="Fecha" value={this.state.formSchedule.start}
onChange={(date) => {
this.state.formSchedule.start = date;
this.setState({ formSchedule: this.state.formSchedule });
}}/>
La classe 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>);
}
}