Ant Design3. DatePicker in X can only select year for processing

Posted by ctsttom on Wed, 26 Jan 2022 12:17:43 +0100

1. Previously on

It was antd2 In version x, the DatePicker component does not support the mode attribute and cannot be set as a year selector alone. However, there is a need to filter according to the year in many parts of the company's projects. Because antd does not support it, the Select component is used to Select the year.

However, the customer's strong Tucao make complaints about the UI style. 😄, Official Tucao make complaints about death! There's no way. I can't convince myself. I can only roll up a YearPicker according to antd's UI style. (time selection control YearPicker is based on React, antd) www.cnblogs.com/zyl-Tara/p/... )However, to be honest, the effect is not ideal. It can only be said that it has achieved the consistency of UI style and the selection of values. However, the clearing of component values and animation transition effects have not been deeply processed.

Fortunately, soon antd3 X finally supports the year selection. Set mode="year" to use the year selector. What a celebration! 😎

2. Problem description

Don't say much, use it quickly! On the code,

import React, { Component } from 'react';
import { DatePicker } from 'antd';

export default class extends Component {
  onChange = val => {
    console.log(val)
  } 
  
  render() {
    return (
        <div>
            <DatePicker 
            placeholder="Please select a year" 
            mode="year" 
            onChange={this.onChange}
            />
        </div>
    );
  }  
}Copy code

The interface presents a selector with only year, nice!

But then, you're confused. No matter how you click the button to select the year, it will not work. The onChange event will not be triggered at all, so value cannot be obtained!

I can't figure it out, and then go to the github issue of ant design. Finally I saw a pertinent comment.

github.com/ant-design/...

<DatePicker mode="year" onPanelChange={(v) => {console.log(v)}}/>Copy code

Just replace onChange with onPanelChange. So you can get time.

However, another problem arises. Although the time is obtained, the panel is not closed.

Continue to find the problem and find that when the DatePicker becomes controlled, you need to open this property to control the closing of the panel.

import React, { Component } from 'react';
import { DatePicker } from 'antd';

export default class extends Component {
  state =  {
    isopen: false,
    time: null
  }
  
  render() {
    const { isopen, time } = this.state
    return (
        <div>
            <DatePicker 
            value={time} 
            open={isopen} 
            mode="year" 
            placeholder="Please select a year"
            format="YYYY" 
            onFocus={() => {this.setState({isopen: true})}} 
            onBlur={() => {this.setState({isopen: false})}} 
            onPanelChange={(v) => {
              console.log(v)
              this.setState({
                time: v,
                isopen: false
              })
              }}/>
        </div>
    );
  }  
}Copy code

At the same time, the display and concealment of the panel when the focus and out of focus are obtained through onFocus and onBlur control.

Everything seems perfect. You can get the value and close the panel normally.

However, the happy time is always short. Soon, the test put forward a defect, "why does the year selector have the effect of flashing on and off after selecting the year, which does not meet the requirements?"

“ 😂, Oh, I'll see again. "

It really flashes. I clearly remember that there was no such problem before. Forget it, let's continue to see where the problem is.

3. Solution

Looking at the document, I found that DatePicker has an onOpenChange method, which is described as follows: the callback of pop-up calendar and close calendar, function(status)

Therefore, you can use the onOpenChange method to determine whether the current operation is to close or open the panel, so as to control the display and concealment of the panel.

Therefore, to sum up all the thoughts, the solution is as follows:

1. The onChange method cannot trigger to get the value. It needs to be replaced with onPanelChange

2. The display and hiding of the panel requires manual control of the open attribute

3. onFocus and onBlur will cause flash on and flash off, which needs to be replaced with onOpenChange

import React, { Component } from 'react';
import { DatePicker } from 'antd';

export default class extends Component {
  state =  {
    isopen: false,
    time: null
  }
  
  render() {
    const { isopen, time } = this.state
    return (
        <div>
            <DatePicker 
            value={time} 
            open={isopen} 
            mode="year"
            placeholder="Please select a year" 
            format="YYYY" 
            onOpenChange={(status) => {
              if(status){
                this.setState({isopen: true})
              } else {
                this.setState({isopen: false})
              }
            }} 
            onPanelChange={(v) => {
              console.log(v)
              this.setState({
                time: v,
                isopen: false
              })
              }}
            />
            onChange={() => {
                this.setState({time: null})
            }}
        </div>
    );
  }  
}Copy code

Now the value can be obtained normally, and the switch panel is smooth without the effect of flashing on and off. Of course, if you are careful, you may find that I used the onChange event in the component and did the operation of setting the value null.

Note: the time here must be set to null. Because the component accepts an object.

Why?

We all know that the DatePicker component has an allowClear attribute, so that we can click in the input box ❌ icon to clear the selected value.

However, when we set mode = "year", the allowClear will not work. What shall I do?

Because the onChange event will not be triggered when the value is selected, but clicking the clear icon will trigger. Therefore, the effect of clearing value can be achieved through the onChange event.

ok, perfect solution ~ 🎉


Author: zhangyanling77
Link: https://juejin.cn/post/6844903859987415047
Source: Nuggets
The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.