Skip to content

feat(datepicker): @Output for year and month selected in multiyear/year #9678

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

Merged
merged 11 commits into from
Feb 6, 2018
Merged

feat(datepicker): @Output for year and month selected in multiyear/year #9678

merged 11 commits into from
Feb 6, 2018

Conversation

julianobrasil
Copy link
Contributor

@Outputs to emit the selected year in multiyear view and the selected month in month view.

image

Closes #9458

@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Jan 30, 2018
@mmalerba mmalerba self-assigned this Jan 30, 2018
Copy link
Contributor

@mmalerba mmalerba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the change! I think people will be really happy about this. We should probably add a section to the docs about it, along with embedded examples.


<h2>Datepicker emulating year picker</h2>
<p>
<input matInput [matDatepicker]="datePicker5" class="datepicker-input-invisible">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hidden input stuff feels kind of hacky. What if we just use the MomentDateAdapter and provide a custom MAT_DATE_FORMATS

Our custom formats could just be a copy of the defaults but with the parse and display formats for dateInput changed to MM/YYYY or YYYY respectively.

As for how to fit this into the demo, you could make some directives demo-moment-month-year, demo-moment-year that provide the appropriate things for their children

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll work on it.

@@ -107,6 +107,18 @@ export class MatCalendar<D> implements AfterContentInit, OnDestroy, OnChanges {
/** Emits when the currently selected date changes. */
@Output() readonly selectedChange = new EventEmitter<D>();

/**
* Emits the year chosen in multiyear view.
* This doesn't implies in change on the selected date.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't imply a change in the selected date.


/**
* Emits the month chosen in year view.
* This doesn't implies in change on the selected date.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't imply a change in the selected date.

@@ -164,6 +164,18 @@ export class MatDatepicker<D> implements OnDestroy {
*/
@Output() readonly selectedChanged: EventEmitter<D> = new EventEmitter<D>();

/**
* Emits selected year in multiyear view.
* This doesn't implies in change on the selected date.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same change to wording here

@@ -65,6 +65,9 @@ export class MatYearView<D> implements AfterContentInit {
/** Emits when a new month is selected. */
@Output() readonly selectedChange = new EventEmitter<D>();

/** Emits the selected month. This doesn't implies in change on the selected date */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same change to wording

@Output() readonly selectedChange = new EventEmitter<D>();

/** Emits the selected year. This doesn't implies in change on the selected date */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same change to wording

@julianobrasil
Copy link
Contributor Author

julianobrasil commented Jan 31, 2018

Well, it's done. There are two things I'm not sure whether I should touch:

  1. A way to disable the period button that switches views: if the developer wants to use this feature to emulate a year/month picker, maybe he/she also wishes to prevent the end user from switching views by clicking on that button.

  2. The docs examples: in one comment above I've writen that maybe the examples should be in a different PR, but I'm having second thoughts about it (because this PR would block the other). Do we still have time for doing this part?

@mmalerba
Copy link
Contributor

mmalerba commented Feb 1, 2018

  1. I think we can save that for another PR (feat(datepicker): Add Custom Header to DatePicker #9639), if we do it at all. There's another PR ongoing to allow specifying a custom header for the calendar which would allow people to address this issue.

  2. I'll leave it up to you whether to do the docs in this PR or a separate one. If you want I can approve this one after all of the comments are addressed and you can start working on the docs. If you finish the docs before this gets merged we can just put it all in this PR.

dateFilter =
(date: Date) => !(date.getFullYear() % 2) && (date.getMonth() % 2) && !(date.getDate() % 2)

onDateInput = (e: MatDatepickerInputEvent<Date>) => this.lastDateInput = e.value;
onDateChange = (e: MatDatepickerInputEvent<Date>) => this.lastDateChange = e.value;

dateCtrl = new FormControl();

constructor() { }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can omit constructor since its not doing anything

}

chosenYearFromYearMonthHandler(year: number) {
try {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you find that these try/catch blocks were necessary for some reason? if the date doesn't parse I believe the forms validation should know about it and you can just display a mat-error

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's something I put in the code and for no reason I left them there. I've just taken it away.

@julianobrasil
Copy link
Contributor Author

You can go on and aprove this one.

@julianobrasil
Copy link
Contributor Author

I have just rebased it.

@mmalerba mmalerba added pr: lgtm target: minor This PR is targeted for the next minor release labels Feb 1, 2018
Copy link
Contributor

@mmalerba mmalerba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 more nit then I'll add merge-ready

dateFilter =
(date: Date) => !(date.getFullYear() % 2) && (date.getMonth() % 2) && !(date.getDate() % 2)

onDateInput = (e: MatDatepickerInputEvent<Date>) => this.lastDateInput = e.value;
onDateChange = (e: MatDatepickerInputEvent<Date>) => this.lastDateChange = e.value;

dateCtrl = new FormControl();
chosenYearHandler(year: number, datepicker: MatDatepicker<Date>) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: these should probably actually be MatDatepicker<Moment> (or MatDatepicker<any> since your code doesn't care)

Copy link
Contributor Author

@julianobrasil julianobrasil Feb 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna use Moment for that just to expose the fact we're using Moment.js.

@mmalerba mmalerba added the action: merge The PR is ready for merge by the caretaker label Feb 1, 2018
@julianobrasil julianobrasil requested a review from amcdnl as a code owner February 1, 2018 10:20
@julianobrasil
Copy link
Contributor Author

julianobrasil commented Feb 1, 2018

Just added docs example and text. I added a subsection in Setting the calendar starting view. Is it appropriate?

image

@@ -51,6 +51,23 @@ year containing the `startAt` date.

<!-- example(datepicker-start-view) -->

#### Watching the views for changes on selected years and months

When a year or a month is selected in **multi-year and year views** respecively, the `yearSelected`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...in the multi-year and year views...

#### Watching the views for changes on selected years and months

When a year or a month is selected in **multi-year and year views** respecively, the `yearSelected`
and `monthSelected` outputs emit the chosen year (full year) and month (0 - 11).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now that I think about this some more, wouldn't it make sense to emit normalized dates
(e.g. new Date(year, 0, 1) and new Date(year, month, 1))? especially for the month case, the month number alone doesn't give you all the info you need

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I'm gonna update this and push it tonight.

@@ -0,0 +1,7 @@
<mat-form-field>
<input matInput [matDatepicker]="dp" placeholder="Choose a year and a month" [formControl]="date">
<mat-datepicker-toggle matSuffix [for]="dp" (yearSelected)="chosenYearHandler($event)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These listeners should go on the datepicker, not the toggle

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ops!

@mmalerba mmalerba removed the action: merge The PR is ready for merge by the caretaker label Feb 1, 2018
@mmalerba
Copy link
Contributor

mmalerba commented Feb 1, 2018

I'm pretty happy with how this turned out. It's actually not that difficult to implement month and year selector with these outputs :)

@julianobrasil
Copy link
Contributor Author

I've changed the first paragraph of datepicker.md. But I'm not sure if it's clear so please have a closer look at it.

#### Watching the views for changes on selected years and months

When a year or a month is selected in `multi-year` and `year` views respecively, the `yearSelected`
and `monthSelected` outputs emit the normalized chosen year and normalized month. By "normalized"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...outputs emit a normalized date representing the chosen year or month. By "normalized" we mean that the dates representing a year will have their month set to January and their day set to the 1st. Dates representing months will have their day set to the 1st of the month. For example, if...

we mean that it will emit an object, not just a number. For example, if `<mat-datepicker>` is
configured to work with javascript native Date objects, the `yearSelected` will emit
`new Date(2017,0,1)` if the user selects 2017 in `multi-year` view. Similarly, `monthSelected`
will emit `new Date(2017,1,0)` if the user selects **Jan** in `year` view and the current date
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jan --> January

configured to work with javascript native Date objects, the `yearSelected` will emit
`new Date(2017,0,1)` if the user selects 2017 in `multi-year` view. Similarly, `monthSelected`
will emit `new Date(2017,1,0)` if the user selects **Jan** in `year` view and the current date
value of the connected `<input>` was something like `new Date(2017,MM,dd)` (the month and year
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

month and day

associated `<input>`.

The following example uses `yearSelected` and `monthSelected` outputs to emulate a month and year
picker (if you're not familiar with the usage of `MomentDateAdapter` and `formats customization`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formats customization ---> MAT_DATE_FORMATS


The following example uses `yearSelected` and `monthSelected` outputs to emulate a month and year
picker (if you're not familiar with the usage of `MomentDateAdapter` and `formats customization`
you can read more about them below in this document to fully understand the example).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

link the words "read more about them" to the correct header in this document.

tslint.json Outdated
@@ -81,7 +81,7 @@
// Disallows importing the whole RxJS library. Submodules can be still imported.
"import-blacklist": [true, "rxjs", "rxjs/operators"],
// Avoids inconsistent linebreak styles in source files. Forces developers to use LF linebreaks.
"linebreak-style": [true, "LF"],
"linebreak-style": [false, "LF"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

were the changes to this file made intentionally? I don't think we want to change these settings

Copy link
Contributor Author

@julianobrasil julianobrasil Feb 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely not. I'm used to switch those to false just to run tslint locally, and this time I forgot to switch them back after tests.

Copy link
Contributor

@mmalerba mmalerba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes!

@mmalerba mmalerba added the action: merge The PR is ready for merge by the caretaker label Feb 1, 2018
@julianobrasil
Copy link
Contributor Author

Just fixed a small nit...

@mmalerba
Copy link
Contributor

mmalerba commented Feb 5, 2018

@julianobrasil This is breaking google's build when I try to presubmit it because we don't sync the moment adapter into google3, but we try to verify that the demo app builds. Could you revert the changes to the demo app? (the examples are what's important to users anyways, demo app is just for the sake of our own manual testing)

@mmalerba mmalerba added presubmit failures This PR has failures in Google's internal presubmit process and cannot be immediately merged and removed action: merge The PR is ready for merge by the caretaker labels Feb 5, 2018
@julianobrasil
Copy link
Contributor Author

julianobrasil commented Feb 6, 2018

I removed the demo changes, but there's still this error in the build process:

6 Feb 02:07:41 - error querying from https://saucelabs.com/rest/v1/angular-ci/tunnels/fa545dcef4e04d65927544a2ab05f0e3, error was: {"message": "Service is temporarily unavailable"}

edit: I had forgotten one last reference to MatMomentModule in demo-material-module.ts

@mmalerba mmalerba added action: merge The PR is ready for merge by the caretaker and removed presubmit failures This PR has failures in Google's internal presubmit process and cannot be immediately merged labels Feb 6, 2018
@mmalerba mmalerba merged commit c2e108e into angular:master Feb 6, 2018
@julianobrasil julianobrasil deleted the featYearMonthPicker branch February 7, 2018 09:53
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(MatDatepicker): observable that emits the seleced year in year mode
3 participants