How to edit the the time picker of material-ui-tim

2019-07-17 01:53发布

I have a material-ui-time-picker and I want to control this input, it works well, but I want to edit the time input from the keyboard and not when I click the input on the clock.

My code is :

import React, { Component } from "react";
import { TimePicker } from "material-ui-time-picker";
import { Input as Time, Dialog as Clock } from "@material-ui/core";

openDialog = () => this.setState({ isOpen: true });
  closeDialog = () => this.setState({ isOpen: false });
  handleDialogTimeChange = newValue => {
    const hours = newValue
      .getHours()
      .toString()
      .padStart(2, "0");
    const minutes = newValue
      .getMinutes()
      .toString()
      .padStart(2, "0");
    const textValue = hours + ":" + minutes;
    this.setState({ time: textValue });
  };
  handleKeyboardTimeChange = time => this.setState({ time });
  createDateFromTextValue = value => {
    const splitParts = value.split(":");
    return new Date(1970, 1, 1, splitParts[0], splitParts[1]);
  };
render() {

    return (

      <div>
        <Time
          value={this.state.time}
          onChange={this.handleKeyboardTimeChange}
          endAdornment={
            <InputAdornment position="end">
              <IconButton onClick={this.openDialog}>
                <AccessTime />
              </IconButton>
            </InputAdornment>
          }
          //}
        />
        <Clock maxWidth="xs" open={this.state.isOpen}>
          <TimePicker
            mode="24h"
            value={this.createDateFromTextValue(this.state.time)}
            onChange={this.handleDialogTimeChange}
            autoOk={true}
            cancelLabel=""
            okLabel=""
            placeholder=""
            disableUnderline={true}
          />
        </Clock>
      </div>
    );
  }

My sandbox: https://codesandbox.io/s/vm9wm19p27

When I run it, I get this input, but when I edit his value, the input will be disappeared.

How can I fix it ?

3条回答
仙女界的扛把子
2楼-- · 2019-07-17 02:22

I think the TimeInput component doesn't allow this, but you can write your own component to create the exact behavior you want. Instead of importing TimeInput import { TimePicker } from the package and create a custom component.

This is in no way fool proof but it will give you the basics to continue. Working example: https://codesandbox.io/embed/5l167pzrx

import React, { useState } from "react";
import { Button, Input, InputAdornment, IconButton, Dialog, DialogActions } from '@material-ui/core';
import { TimePicker } from 'material-ui-time-picker';
import AccessTime from '@material-ui/icons/AccessTime';

function CustomDatePicker() {
  const [isOpen, setIsOpen] = useState(false);
  const [value, setValue] = useState('10:10');

  const openDialog = () => setIsOpen(true);
  const closeDialog = () => setIsOpen(false);

  const handleDialogTimeChange = (newValue) => {
    const hours = newValue.getHours().toString().padStart(2, "0");
    const minutes = newValue.getMinutes().toString().padStart(2, "0")
    const textValue = hours + ':' + minutes;
    setValue(textValue);
  }
  const handleKeyboardTimeChange = (event) => setValue(event.target.value);

  const createDateFromTextValue = value => {
    const splitParts = value.split(':');
    return new Date(1970, 1, 1, splitParts[0], splitParts[1]);
  }

  return (
    <div>
      <Input
        value={value}
        onChange={handleKeyboardTimeChange}
        endAdornment={
        <InputAdornment position="end">
          <IconButton onClick={openDialog}>
            <AccessTime />
          </IconButton>
        </InputAdornment>
      }
      />
      <Dialog maxWidth='xs' open={isOpen}>
        <TimePicker mode='24h' value={createDateFromTextValue(value)} onChange={handleDialogTimeChange} />
        <DialogActions>
        <Button onClick={closeDialog} color='primary'>
          Cancel
        </Button>
        <Button onClick={closeDialog} color='primary'>
          Ok
        </Button>
        </DialogActions>
      </Dialog>
    </div>
  )
}

export default CustomDatePicker
查看更多
手持菜刀,她持情操
3楼-- · 2019-07-17 02:27

Look at this example:
https://mui.wertarbyte.com/#timepicker

You can replace the button in the example by a TextField with an icon and only when you click on the icon open a TimePicker instead of TimeInput or you can use the TimePicker of the material-ui-pickers package

Material-ui-pickers demo: https://material-ui-pickers.dev/api/timepicker#keyboard-input

查看更多
再贱就再见
4楼-- · 2019-07-17 02:47

One solution component has been provided in their Github repository. Please check this out, it's an already know issue with material-ui and has already been accepted as a solution.This is the solution provided there incase the link becomes obsolete:

'use strict';
import React, {Component} from 'react';
import {DatePicker, IconButton, TextField} from "material-ui";
import ActionDateRange from 'material-ui/svg-icons/action/date-range';
import format from 'date-fns/format'
import parse from 'date-fns/parse'

export default class DatePickerField extends Component{

   constructor(props){
      super(props);

      this.state = {
        selectedDate: new Date(),
        dateText: format(new Date(), 'MM/DD/YYYY')
      };
   }

   handleChangeDatePicker = (event, date) => {
      this.setState({selectedDate: date, dateText:format(date, 'MM/DD/YYYY')});
   };

   handleDateInputChange = (event, value) => {
      this.setState({dateText:value});
   };

   handleDateInputBlur = (value) => {
     let parsedDate = parse(value, 'MM/DD/YYYY');

     if(this.isADate(parsedDate)){
        this.setState({selectedDate:parsedDate});
     }
     else{
        this.setState({dateText:format(this.state.selectedDate, 'MM/DD/YYYY')});
     }
   };

   isADate = (maybeDate) => {
      if ( Object.prototype.toString.call(maybeDate) === "[object Date]" ) {
         if ( isNaN( maybeDate.getTime() ) ) {
            return false;
         }
         else {
            return true;
         }
      }
      else {
         return false;
      }
   };

   render(){

      let dateInputWidth = "150px";
      let datePickerMargin = "-185px";

      return (
         <div style={{display: "flex"}}>
            <TextField
               style={{width:dateInputWidth}}
               value={this.state.dateText}
               onChange={this.handleDateInputChange}
               onBlur={(event) => this.handleDateInputBlur(event.currentTarget.value)}
            />

            <IconButton style={{opacity:"0.65"}}
                        onClick={() => this.datePicker.focus()}>
               <ActionDateRange />
            </IconButton>

            <div style={{width:"0px", height:"0px", marginLeft:datePickerMargin}}>
               <DatePicker
                  id="dataPicker"
                  floatingLabelText={''}
                  value={this.state.selectedDate}
                  errorText={''}
                  disabled={false}
                  formatDate={date => { return format(date, 'MM/DD/YYYY') } }
                  autoOk
                  container="inline"
                  fullWidth
                  onChange={this.handleChangeDatePicker}
                  ref={c => {
                     this.datePicker = c
                  }}
               />
            </div>
         </div>
      )
   }

}

If you face the problem Cannot find prepareStyles of undefined error, please check if you have defined the theme as provider prior to any component usage, or else it won't work. Check this note:

Beginning with v0.15.0, Material-UI components require a theme to be provided. The quickest way to get up and running is by using the MuiThemeProvider to inject the theme into your application context.

And this is the sample snippet to show how to accomplish that:

In your App.js

 import React from 'react';
 import ReactDOM from 'react-dom';
 import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
 import MyAwesomeReactComponent from './MyAwesomeReactComponent';

 const App = () => (
   <MuiThemeProvider>
     <MyAwesomeReactComponent />
   </MuiThemeProvider>
 );

 ReactDOM.render(
   <App />,
   document.getElementById('app')
 );

And in your ./MyAwesomeReactComponent.js (that is the component you want to work witk):

import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';

const MyAwesomeReactComponent = () => (
    <RaisedButton label="Default" />
);

export default MyAwesomeReactComponent;

Please refer to their official usage guide for further details.

查看更多
登录 后发表回答