-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Personal details - DOB field updating once year or month has been changed #18577
Personal details - DOB field updating once year or month has been changed #18577
Conversation
d3dd9c2
to
76a353f
Compare
@roryabraham @Santhosh-Sellavel One of you needs to copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
86744b1
to
e8e0e6f
Compare
@@ -19,7 +19,9 @@ class CalendarPicker extends React.PureComponent { | |||
constructor(props) { | |||
super(props); | |||
|
|||
let currentDateView = props.value; | |||
const currentSelection = moment(props.value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need to pass a format for date to parse the value here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to format it cause it is not used to display date itself - the date that is displayed in the input is build from state string values selectedYear
, selectedMonth
and selectedDay
(we need to store them this way cause we need to allow incorrect dates in the input field).
The currentSelection
moment object is used only temporarily to make translate props.value
date into these three state values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
props.value
is the date string. If then don't we need to pass a format for parsing value from the string correctly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh, right - it's not necessary but it is recommended to pass it as a constructor parameter... Probably to make it easier for parser to parse the date (it's pitty they didn't explain the reason in the docs). I'll add it, then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved
If the steps are the same across Test, offline, and QA Steps sections. we can just leave a comment the same as the other section instead of repeating it. |
Refer to the below-linked video Issues_DatePICKET.mov
From Step 1 to Step 5, made the date valid to invalid but no error was shown, but after Step 6 we show an error. But we made the date valid in step 7 and made it invalid in step 8 and this time we show an error. Whenever there is invalid date we should show error straightaway as discussed here Also there is a weird mix-up on step 3 date was set wrongly. cc: @roryabraham |
e8e0e6f
to
bf1d616
Compare
Hey @Santhosh-Sellavel! Thanks for your feedback. All the issues shown in your video are addressed now (date changes correctly, validation is now performed on every date change). Please re-check it, thanks. |
*/ | ||
setDate(selectedDate) { | ||
this.setState({selectedDate}, () => { | ||
this.props.onInputChange(selectedDate); | ||
this.props.onBlur(); // force validation on every date change |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a weird or sort of hacky thing to do. This will make validation occur twice.
The problem is in the Form
Component. Specifically here
Line 196 in 756e9d8
const errors = _.pick(validationErrors, (inputValue, inputID) => Boolean(this.touchedInputs[inputID])); |
The touchedInputs
is not set.
We set touchedInputs
here on blur. This makes sense as we don't want to show an error on every change in the input, instead only when focusing on a different input in the form.
Lines 296 to 303 in 756e9d8
onBlur: (event) => { | |
// We delay the validation in order to prevent Checkbox loss of focus when | |
// the user are focusing a TextInput and proceeds to toggle a CheckBox in | |
// web and mobile web platforms. | |
setTimeout(() => { | |
this.setTouchedInput(inputID); | |
this.validate(this.state.inputValues); | |
}, 200); |
But in our case validation needs in every change maybe we should look for a way to set the touchedInputs
once or prop to just to show validation errors without considering the touchedInputs
your thoughts? @burczu @roryabraham
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't say it's hack-ish solution here - custom form fields like this date picker should decide on their own when they are considered "blurred", and call suitable event handler then.
Of course, it is also connected to the touched state, but I think this state is more internal thing from the form perspective. What I think as an alternative solution is to provide the onTouched
event handler, that could be called by the form field instead of calling onBlur
but effectively it would be the same thing done in slightly different way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I think as an alternative solution is to provide the onTouched event handler, that could be called by the form field instead of calling onBlur but effectively it would be the same thing done in slightly different way.
@burczu Can you elaborate more with implementation details?
@roryabraham Your thoughts so far?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Santhosh-Sellavel Here, in the Form.js
:
Lines 285 to 329 in dd5fbb6
return React.cloneElement(child, { | |
ref: (node) => { | |
this.inputRefs[inputID] = node; | |
const {ref} = child; | |
if (_.isFunction(ref)) { | |
ref(node); | |
} | |
}, | |
value: this.state.inputValues[inputID], | |
errorText: this.state.errors[inputID] || fieldErrorMessage, | |
onBlur: (event) => { | |
// We delay the validation in order to prevent Checkbox loss of focus when | |
// the user are focusing a TextInput and proceeds to toggle a CheckBox in | |
// web and mobile web platforms. | |
setTimeout(() => { | |
this.setTouchedInput(inputID); | |
this.validate(this.state.inputValues); | |
}, 200); | |
if (_.isFunction(child.props.onBlur)) { | |
child.props.onBlur(event); | |
} | |
}, | |
onInputChange: (value, key) => { | |
const inputKey = key || inputID; | |
this.setState( | |
(prevState) => ({ | |
inputValues: { | |
...prevState.inputValues, | |
[inputKey]: value, | |
}, | |
}), | |
() => this.validate(this.state.inputValues), | |
); | |
if (child.props.shouldSaveDraft) { | |
FormActions.setDraftValues(this.props.formID, {[inputKey]: value}); | |
} | |
if (child.props.onValueChange) { | |
child.props.onValueChange(value); | |
} | |
}, | |
}); |
where we are injecting props to the children, and we can inject one another - onTouched
:
onBlur: () => {
...
},
onTouched: () => {
this.setTouchedInput(inputID);
},
onInputChange: () => {
...
}
and then, in new the NewDatePicker
component, instead of calling this.props.onBlur()
ever time we change the date, we could call this.props.onTouched()
.
Effect is the same, the validation message appears right after we select incorrect date, but I don't think it is the best solution - the touchedInput
state is an internal value of the Form
component and I don't believe we should allow form fields to amend it directly.
Also, when you check to docs about Creating and using Forms you can find here that the onBlur
callback is designed to call validation directly (at least I understand it this way):
"- onBlur: An onBlur handler that calls validate."
As I wrote in my previous comment - I believe the custom field should decide when it is considered as blurred, so calling this.props.onBlur
on every date change might be correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me your thoughts @roryabraham
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, @roryabraham - your opinion would be appreciated here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roryabraham bump!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the custom field should decide when it is considered as blurred, so calling this.props.onBlur on every date change might be correct
The only thing I can imagine might be problematic with this is that it could cause the input to lose accessibility focus with every change, which would be annoying for screen readers. However, I'm not confident in this because I'm not experienced with using screen readers
the touchedInput state is an internal value of the Form component and I don't believe we should allow form fields to amend it directly
I don't think I agree with this. If a child input should be able to control when it is blurred, shouldn't it also be able to control when it's touched?
So I'd suggest the alternate solution where we give the child an onTouched
prop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Santhosh-Sellavel @roryabraham the alternate solution is now applied
2b3b3f2
to
e09e680
Compare
Heads up @burczu, looks like tests are failing |
Hey @roryabraham, I've noticed. I need to finish another urgent task first, and then I'll get back to this one, make a change discussed with @Santhosh-Sellavel and take a look at tests too. |
386a3cc
to
22c9eca
Compare
All the tests should be fixed now |
Reviewer Checklist
Screenshots/VideosWeb & DesktopScreen.Recording.2023-05-26.at.1.27.56.AM.movMobile Web - Chrome & Mobile Web - SafariScreen.Recording.2023-05-26.at.2.03.58.AM.moviOS & AndroidScreen.Recording.2023-05-26.at.2.06.58.AM.mov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, tests well!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @burczu and @Santhosh-Sellavel
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to staging by https://github.com/mountiny in version: 1.3.20-0 🚀
|
I think this PR introduced this regression. |
It's not critical, but we should figure out what ''Fix the errors' should be doing, now that the input is not selectable. |
@Julesssss Left a comment here |
🚀 Deployed to production by https://github.com/Julesssss in version: 1.3.20-5 🚀
|
Details
This PR changes the behaviour of the Calendar Picker component in the way where not only selecting a day means selecting the whole date but also changing a year or month selects the date. In case of selecting an invalid date, the error message is displayed.
Fixed Issues
$ #16514
PROPOSAL: #16514 (comment)
Tests
Happy path
Changing a month
Changing a year
Offline tests
The same as above.
QA Steps
The same as above.
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Web
screen-capture-16514.mp4
Mobile Web - Chrome
screen-capture-16514-android-web.mp4
Mobile Web - Safari
screen-capture-16514-ios-web.mp4
Desktop
screen-capture-16514-desktop.mp4
iOS
screen-capture-16514-ios.mp4
Android
screen-capture-16514-android.mp4