From 8dbca115baef115005237cb4c7de6f84648a8da0 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Fri, 13 Oct 2017 15:58:04 -0700 Subject: [PATCH 1/4] make some tweaks to datepicker docs --- src/lib/datepicker/datepicker.md | 126 ++++++++++++++++++++++++------- 1 file changed, 99 insertions(+), 27 deletions(-) diff --git a/src/lib/datepicker/datepicker.md b/src/lib/datepicker/datepicker.md index 6a3ee7a32861..699497cc685c 100644 --- a/src/lib/datepicker/datepicker.md +++ b/src/lib/datepicker/datepicker.md @@ -1,18 +1,10 @@ The datepicker allows users to enter a date either through text input, or by choosing a date from -the calendar. It is made up of several components and directives that work together: +the calendar. It is made up of several components and directives that work together. -### Current state -Currently the datepicker is in the beginning stages and supports basic date selection functionality. -There are many more features that will be added in future iterations, including: - * Support for datetimes (e.g. May 2, 2017 at 12:30pm) and month + year only (e.g. May 2017) - * Support for selecting and displaying date ranges - * Support for custom time zones - * Infinite scrolling through calendar months - * Built in support for [Moment.js](https://momentjs.com/) dates - ### Connecting a datepicker to an input + A datepicker is composed of a text input and a calendar pop-up, connected via the `matDatepicker` property on the text input. @@ -41,19 +33,44 @@ can easily be used as a prefix or suffix on the material input: ``` ### Setting the calendar starting view + By default the calendar will open in month view, this can be changed by setting the `startView` -property of `mat-datepicker` to `"year"`. In year view the user will see all months of the year and +property of `` to `year`. In year view the user will see all months of the year and then proceed to month view after choosing a month. The month or year that the calendar opens to is determined by first checking if any date is currently selected, if so it will open to the month or year containing that date. Otherwise it will open to the month or year containing today's date. This behavior can be overridden by using the -`startAt` property of `mat-datepicker`. In this case the calendar will open to the month or year +`startAt` property of ``. In this case the calendar will open to the month or year containing the `startAt` date. +### Setting the selected date + +The type of values that the datepicker expects actually depends on the particular `DateAdapter` that +you're using in your app. For example when using the `NativeDateAdapter` the datepicker expects +`Date` objects, and when using the `MomentDateAdapter` it expects `Moment` objects. You can also +create your own `DateAdapter` that works with whatever date type you want. (For more information +about this see the section on +[choosing a date implementation](#choosing-a-date-implementation-and-date-format-settings)). + +Depending on the `DateAdapter` you're using, the datepicker may automatically deserialize certain +date formats for you as well. For example, both the `NativeDateAdapter` and `MomentDateAdapter` +allow [ISO 8601](https://tools.ietf.org/html/rfc3339) strings to be passed to the datepicker and +automatically converted to the proper object type. This can be convenient when binding data directly +from your backend to the datepicker. However, when possible, you should pass the appropriate object +type. The datepicker will not accept date strings formatted in user format such as `"1/2/2017"` as +this is ambiguous and will mean different things depending on the locale of the browser running the +code. + +As with other types of ``, the datepicker works with `@angular/forms` directives such as +`formGroup`, `formControl`, `ngModel`, etc. + + + ### Date validation + There are three properties that add date validation to the datepicker input. The first two are the `min` and `max` properties. In addition to enforcing validation on the input, these properties will disable all dates on the calendar popup before or after the respective values and prevent the user @@ -84,31 +101,51 @@ Each validation property has a different error that can be checked: * A value that violates the `matDatepickerFilter` property will have a `matDatepickerFilter` error. ### Input and change events -The input's native `input` and `change` events will only trigger due to user interaction with the -input element; they will not fire when the user selects a date from the calendar popup. Because of -this limitation, the datepicker input also has support for `dateInput` and `dateChange` events. -These trigger when the user interacts with either the input or the popup. + +The input's native `(input)` and `(change)` events will only trigger due to user interaction with +the input element; they will not fire when the user selects a date from the calendar popup. Because +of this limitation, the datepicker input also has support for `(dateInput)` and `(dateChange)` +events. These trigger when the user interacts with either the input or the popup. + +The `(dateInput)` event will fire whenever the value changes due to the user typing or selecting a +date from the calendar. The `(dateChange)` event will fire whenever the user finishes typing input +(on `` blur), or when the user chooses a date from the calendar. + + ```html ``` +### Disabling parts of the datepicker + +As with any standard ``, it is possible to disable the datepicker input by adding the +`disabled` property. By default the `` and `` will inherit +their disabled state from the ``, but this can be overridden by setting the `disabled` +property on the datepicker or toggle elements. This can be useful if you want to disable text input +but allow selection via the calendar or vice-versa. + + + ### Touch UI mode + The datepicker normally opens as a popup under the input. However this is not ideal for touch devices that don't have as much screen real estate and need bigger click targets. For this reason -`mat-datepicker` has a `touchUi` property that can be set to `true` in order to enable a more touch -friendly UI where the calendar opens in a large dialog. +`` has a `touchUi` property that can be set to `true` in order to enable a more +touch friendly UI where the calendar opens in a large dialog. ### Manually opening and closing the calendar + The calendar popup can be programmatically controlled using the `open` and `close` methods on the -`mat-datepicker`. It also has an `opened` property that reflects the status of the popup. +``. It also has an `opened` property that reflects the status of the popup. ### Internationalization + In order to support internationalization, the datepicker supports customization of the following three pieces via injection: 1. The date implementation that the datepicker accepts. @@ -116,6 +153,7 @@ three pieces via injection: 3. The message strings used in the datepicker's UI. #### Setting the locale code + By default, the `MAT_DATE_LOCALE` injection token will use the existing `LOCALE_ID` locale code from `@angular/core`. If you want to override it, you can provide a new value for the `MAT_DATE_LOCALE` token: @@ -145,14 +183,19 @@ export class FooComponent { } ``` + + #### Choosing a date implementation and date format settings + The datepicker was built to be date implementation agnostic. This means that it can be made to work with a variety of different date implementations. However it also means that developers need to make sure to provide the appropriate pieces for the datepicker to work with their chosen implementation. -The easiest way to ensure this is just to import one of the pre-made modules (currently -`MatNativeDateModule` is the only implementation that ships with material, but there are plans to add -a module for Moment.js support): - * `MatNativeDateModule` - support for native JavaScript Date object +The easiest way to ensure this is just to import one of the pre-made modules: + +|Module |Date type|Supported locales |Dependencies |Import from | +|---------------------|---------|-----------------------------------------------------------------------|----------------------------------|----------------------------------| +|`MatNativeDateModule`|`Date` |en-US |None |`@angular/material` | +|`MatMomentDateModule`|`Moment` |[See project](https://github.com/moment/moment/tree/develop/src/locale)|[Moment.js](https://momentjs.com/)|`@angular/material-moment-adapter`| These modules include providers for `DateAdapter` and `MAT_DATE_FORMATS` @@ -177,10 +220,14 @@ export class MyComponent { *Please note: `MatNativeDateModule` is based off of the functionality available in JavaScript's native `Date` object, and is thus not suitable for many locales. One of the biggest shortcomings of -the native `Date` object is the inability to set the parse format. We highly recommend using a -custom `DateAdapter` that works with the formatting/parsing library of your choice.* +the native `Date` object is the inability to set the parse format. We highly recommend using the +`MomentDateAdapter` or a custom `DateAdapter` that works with the formatting/parsing library of your +choice.* + + #### Customizing the date implementation + The datepicker does all of its interaction with date objects via the `DateAdapter`. Making the datepicker work with a different date implementation is as easy as extending `DateAdapter`, and using your subclass as the provider. You will also want to make sure that the `MAT_DATE_FORMATS` @@ -197,12 +244,14 @@ provided in your app are formats that can be understood by your date implementat export class MyApp {} ``` + + #### Customizing the parse and display formats + The `MAT_DATE_FORMATS` object is just a collection of formats that the datepicker uses when parsing and displaying dates. These formats are passed through to the `DateAdapter` so you will want to make sure that the format objects you're using are compatible with the `DateAdapter` used in your app. -This example shows how to use the native `Date` implementation from material, but with custom -formats. +This example shows how to use the `NativeDateAdapter`, but with custom formats. ```ts @NgModule({ @@ -215,7 +264,10 @@ formats. export class MyApp {} ``` + + #### Localizing labels and messages + The various text strings used by the datepicker are provided through `MatDatepickerIntl`. Localization of these messages can be done by providing a subclass with translated values in your application root module. @@ -229,7 +281,11 @@ application root module. }) export class MyApp {} ``` + + + ### Accessibility + The `MatDatepickerInput` directive adds `aria-haspopup` attribute to the native input element, and it triggers a calendar dialog with `role="dialog"`. @@ -238,6 +294,7 @@ should have a placeholder or be given a meaningful label via `aria-label`, `aria `MatDatepickerIntl`. #### Keyboard shortcuts + The keyboard shortcuts to handle datepicker are: | Shortcut | Action | @@ -278,3 +335,18 @@ In year view: | `PAGE_DOWN` | Go to next year | | `ALT` + `PAGE_DOWN` | Go to next 10 years | | `ENTER` | Select current month | + +### Future work + +Currently the datepicker supports basic date selection functionality. There are more features that +will be added in future iterations, including: + * Support for datetimes (e.g. May 2, 2017 at 12:30pm) and month + year only (e.g. May 2017) + * Support for selecting and displaying date ranges + * Support for custom time zones + * Infinite scrolling through calendar months + * Easier year selection + * Custom views for the calendar popup + +### Troubleshooting + + From 5640b1d32b06bcdf8307a91b00de967ab5626a9e Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Mon, 16 Oct 2017 17:31:17 -0700 Subject: [PATCH 2/4] add examples --- src/demo-app/system-config.ts | 1 + src/demo-app/tsconfig-aot.json | 2 + src/demo-app/tsconfig-build.json | 2 + src/demo-app/tsconfig.json | 5 +- src/e2e-app/system-config.ts | 1 + src/e2e-app/tsconfig-build.json | 1 + src/e2e-app/tsconfig.json | 1 + src/lib/datepicker/datepicker-errors.ts | 3 +- src/lib/datepicker/datepicker.md | 77 ++++++++++--------- src/lib/datepicker/datepicker.ts | 2 +- .../datepicker-api/datepicker-api-example.ts | 7 +- .../datepicker-disabled-example.css | 1 + .../datepicker-disabled-example.html | 23 ++++++ .../datepicker-disabled-example.ts | 9 +++ .../datepicker-events-example.css | 6 ++ .../datepicker-events-example.html | 10 +++ .../datepicker-events-example.ts | 16 ++++ .../datepicker-filter-example.ts | 4 +- .../datepicker-formats-example.css | 1 + .../datepicker-formats-example.html | 5 ++ .../datepicker-formats-example.ts | 44 +++++++++++ .../datepicker-locale-example.css | 1 + .../datepicker-locale-example.html | 7 ++ .../datepicker-locale-example.ts | 28 +++++++ .../datepicker-min-max-example.ts | 4 +- .../datepicker-moment-example.css | 1 + .../datepicker-moment-example.html | 5 ++ .../datepicker-moment-example.ts | 30 ++++++++ .../datepicker-overview-example.ts | 4 +- .../datepicker-start-view-example.ts | 4 +- .../datepicker-touch-example.ts | 7 +- .../datepicker-value-example.css | 1 + .../datepicker-value-example.html | 18 +++++ .../datepicker-value-example.ts | 13 ++++ src/material-examples/example-module.ts | 62 +++++++++++++-- src/material-examples/package.json | 3 +- src/material-examples/tsconfig-build.json | 3 + src/material-examples/tsconfig-es5.json | 3 + src/material-examples/tsconfig.json | 5 +- tools/gulp/tasks/e2e.ts | 8 +- tools/package-tools/rollup-globals.ts | 1 + 41 files changed, 358 insertions(+), 71 deletions(-) create mode 100644 src/material-examples/datepicker-disabled/datepicker-disabled-example.css create mode 100644 src/material-examples/datepicker-disabled/datepicker-disabled-example.html create mode 100644 src/material-examples/datepicker-disabled/datepicker-disabled-example.ts create mode 100644 src/material-examples/datepicker-events/datepicker-events-example.css create mode 100644 src/material-examples/datepicker-events/datepicker-events-example.html create mode 100644 src/material-examples/datepicker-events/datepicker-events-example.ts create mode 100644 src/material-examples/datepicker-formats/datepicker-formats-example.css create mode 100644 src/material-examples/datepicker-formats/datepicker-formats-example.html create mode 100644 src/material-examples/datepicker-formats/datepicker-formats-example.ts create mode 100644 src/material-examples/datepicker-locale/datepicker-locale-example.css create mode 100644 src/material-examples/datepicker-locale/datepicker-locale-example.html create mode 100644 src/material-examples/datepicker-locale/datepicker-locale-example.ts create mode 100644 src/material-examples/datepicker-moment/datepicker-moment-example.css create mode 100644 src/material-examples/datepicker-moment/datepicker-moment-example.html create mode 100644 src/material-examples/datepicker-moment/datepicker-moment-example.ts create mode 100644 src/material-examples/datepicker-value/datepicker-value-example.css create mode 100644 src/material-examples/datepicker-value/datepicker-value-example.html create mode 100644 src/material-examples/datepicker-value/datepicker-value-example.ts diff --git a/src/demo-app/system-config.ts b/src/demo-app/system-config.ts index e67879e8575d..b42b8b36c17a 100644 --- a/src/demo-app/system-config.ts +++ b/src/demo-app/system-config.ts @@ -29,6 +29,7 @@ System.config({ // TODO(devversion): replace once the index.ts file for the Material package has been added. '@angular/material': 'dist/packages/material/public-api.js', + '@angular/material-moment-adapter': 'dist/packages/material-moment-adapter/public-api.js', '@angular/cdk': 'dist/packages/cdk/index.js', '@angular/cdk/a11y': 'dist/packages/cdk/a11y/index.js', '@angular/cdk/accordion': 'dist/packages/cdk/accordion/index.js', diff --git a/src/demo-app/tsconfig-aot.json b/src/demo-app/tsconfig-aot.json index fb9cc74893ed..bf6136c9d33a 100644 --- a/src/demo-app/tsconfig-aot.json +++ b/src/demo-app/tsconfig-aot.json @@ -4,6 +4,8 @@ { "extends": "./tsconfig-build", "compilerOptions": { + // Needed for Moment.js since it doesn't have a default export. + "allowSyntheticDefaultImports": true, "experimentalDecorators": true, // TODO(paul): Remove once Angular has been upgraded and supports noUnusedParameters in AOT. "noUnusedParameters": false, diff --git a/src/demo-app/tsconfig-build.json b/src/demo-app/tsconfig-build.json index 8ad4d20b6c8e..a21a670730a6 100644 --- a/src/demo-app/tsconfig-build.json +++ b/src/demo-app/tsconfig-build.json @@ -2,6 +2,8 @@ // since the demo-app will be served in the browser. { "compilerOptions": { + // Needed for Moment.js since it doesn't have a default export. + "allowSyntheticDefaultImports": true, "declaration": false, "emitDecoratorMetadata": true, "experimentalDecorators": true, diff --git a/src/demo-app/tsconfig.json b/src/demo-app/tsconfig.json index f7f702c1c807..e1156619275c 100644 --- a/src/demo-app/tsconfig.json +++ b/src/demo-app/tsconfig.json @@ -2,12 +2,15 @@ { "extends": "../../tsconfig.json", "compilerOptions": { + // Needed for Moment.js since it doesn't have a default export. + "allowSyntheticDefaultImports": true, "rootDir": "..", "baseUrl": ".", "paths": { "@angular/cdk/*": ["../cdk/*"], "@angular/material/*": ["../lib/*"], - "@angular/material": ["../lib/public-api.ts"] + "@angular/material": ["../lib/public-api.ts"], + "@angular/material-moment-adapter": ["../material-moment-adapter/public-api.ts"] } }, "include": ["./**/*.ts"] diff --git a/src/e2e-app/system-config.ts b/src/e2e-app/system-config.ts index 291c4a71f0fd..3037d29c232c 100644 --- a/src/e2e-app/system-config.ts +++ b/src/e2e-app/system-config.ts @@ -26,6 +26,7 @@ System.config({ 'node:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', '@angular/material': 'dist/bundles/material.umd.js', + '@angular/material-moment-adapter': 'dist/bundles/material-moment-adapter.umd.js', '@angular/cdk': 'dist/bundles/cdk.umd.js', '@angular/cdk/a11y': 'dist/bundles/cdk-a11y.umd.js', '@angular/cdk/accordion': 'dist/bundles/cdk-accordion.umd.js', diff --git a/src/e2e-app/tsconfig-build.json b/src/e2e-app/tsconfig-build.json index b7d368a5e3ea..c6942221368c 100644 --- a/src/e2e-app/tsconfig-build.json +++ b/src/e2e-app/tsconfig-build.json @@ -27,6 +27,7 @@ "@angular/cdk/*": ["./cdk/*"], "@angular/material": ["./material"], "@angular/material/*": ["./material/*"], + "@angular/material-moment-adapter": ["./material-moment-adapter"], "@angular/material-examples": ["./material-examples"] } }, diff --git a/src/e2e-app/tsconfig.json b/src/e2e-app/tsconfig.json index aef9e39b38e8..411e2992a444 100644 --- a/src/e2e-app/tsconfig.json +++ b/src/e2e-app/tsconfig.json @@ -8,6 +8,7 @@ "@angular/cdk/*": ["../cdk/*"], "@angular/material/*": ["../lib/*"], "@angular/material": ["../lib/public-api.ts"], + "@angular/material-moment-adapter": ["../material-moment-adapter/public-api.ts"], "@angular/material-examples": ["../material-examples/public-api.ts"] } }, diff --git a/src/lib/datepicker/datepicker-errors.ts b/src/lib/datepicker/datepicker-errors.ts index 1d0539290496..72850da997f1 100644 --- a/src/lib/datepicker/datepicker-errors.ts +++ b/src/lib/datepicker/datepicker-errors.ts @@ -10,5 +10,6 @@ export function createMissingDateImplError(provider: string) { return Error( `MatDatepicker: No provider found for ${provider}. You must import one of the following ` + - `modules at your application root: MatNativeDateModule, or provide a custom implementation.`); + `modules at your application root: MatNativeDateModule, MatMomentDateModule, or provide a ` + + `custom implementation.`); } diff --git a/src/lib/datepicker/datepicker.md b/src/lib/datepicker/datepicker.md index 699497cc685c..6be1d7f3f58e 100644 --- a/src/lib/datepicker/datepicker.md +++ b/src/lib/datepicker/datepicker.md @@ -49,10 +49,10 @@ containing the `startAt` date. ### Setting the selected date The type of values that the datepicker expects actually depends on the particular `DateAdapter` that -you're using in your app. For example when using the `NativeDateAdapter` the datepicker expects +you're using in your app. For example, when using the `NativeDateAdapter` the datepicker expects `Date` objects, and when using the `MomentDateAdapter` it expects `Moment` objects. You can also create your own `DateAdapter` that works with whatever date type you want. (For more information -about this see the section on +about this, see the section on [choosing a date implementation](#choosing-a-date-implementation-and-date-format-settings)). Depending on the `DateAdapter` you're using, the datepicker may automatically deserialize certain @@ -67,7 +67,7 @@ code. As with other types of ``, the datepicker works with `@angular/forms` directives such as `formGroup`, `formControl`, `ngModel`, etc. - + ### Date validation @@ -111,22 +111,17 @@ The `(dateInput)` event will fire whenever the value changes due to the user typ date from the calendar. The `(dateChange)` event will fire whenever the user finishes typing input (on `` blur), or when the user chooses a date from the calendar. - - -```html - - -``` + ### Disabling parts of the datepicker As with any standard ``, it is possible to disable the datepicker input by adding the -`disabled` property. By default the `` and `` will inherit +`disabled` property. By default, the `` and `` will inherit their disabled state from the ``, but this can be overridden by setting the `disabled` property on the datepicker or toggle elements. This can be useful if you want to disable text input but allow selection via the calendar or vice-versa. - + ### Touch UI mode @@ -169,21 +164,7 @@ export class MyApp {} It's also possible to set the locale at runtime using the `setLocale` method of the `DateAdapter`. -```ts -import { DateAdapter, NativeDateAdapter } from '@angular/material'; - -@Component({ - selector: 'foo', - template: '' -}) -export class FooComponent { - constructor(dateAdapter: DateAdapter) { - dateAdapter.setLocale('de-DE'); - } -} -``` - - + #### Choosing a date implementation and date format settings @@ -224,10 +205,12 @@ the native `Date` object is the inability to set the parse format. We highly rec `MomentDateAdapter` or a custom `DateAdapter` that works with the formatting/parsing library of your choice.* - + #### Customizing the date implementation + + The datepicker does all of its interaction with date objects via the `DateAdapter`. Making the datepicker work with a different date implementation is as easy as extending `DateAdapter`, and using your subclass as the provider. You will also want to make sure that the `MAT_DATE_FORMATS` @@ -244,27 +227,28 @@ provided in your app are formats that can be understood by your date implementat export class MyApp {} ``` - - #### Customizing the parse and display formats The `MAT_DATE_FORMATS` object is just a collection of formats that the datepicker uses when parsing and displaying dates. These formats are passed through to the `DateAdapter` so you will want to make sure that the format objects you're using are compatible with the `DateAdapter` used in your app. -This example shows how to use the `NativeDateAdapter`, but with custom formats. + +If you want use one of the `DateAdapters` that ships with Angular Material, but use your own +`MAT_DATE_FORMATS`, you can import the `NativeDateModule` or `MomentDateModule`. These modules are +identical to the "Mat"-prefixed versions (`MatNativeDateModule` and `MatMomentDateModule`) except +they do not include the default formats. For example: ```ts @NgModule({ - imports: [MatDatepickerModule], + imports: [MatDatepickerModule, NativeDateModule], providers: [ - {provide: DateAdapter, useClass: NativeDateAdapter}, {provide: MAT_DATE_FORMATS, useValue: MY_NATIVE_DATE_FORMATS}, ], }) export class MyApp {} ``` - + #### Localizing labels and messages @@ -282,8 +266,6 @@ application root module. export class MyApp {} ``` - - ### Accessibility The `MatDatepickerInput` directive adds `aria-haspopup` attribute to the native input element, and it @@ -349,4 +331,27 @@ will be added in future iterations, including: ### Troubleshooting - +#### Error: MatDatepicker: No provider found for DateAdapter/MAT_DATE_FORMATS + +This error is thrown if you have not provided all of the injectables the datepicker needs to work. +The easiest way to resolve this is to import the `MatNativeDateModule` or `MatMomentDateModule` in +your application's root module. See the section on +[choosing a date implementation](#choosing-a-date-implementation-and-date-format-settings)) for more +information. + +#### Error: A MatDatepicker can only be associated with a single input + +This error is thrown if more than one `` tries to claim ownership over the same +`` (via the `matDatepicker` attribute on the input). A datepicker can only be +associated with a single input. + +#### Error: Attempted to open an MatDatepicker with no associated input. + +This error occurs if your `` is not associated with any ``. To associate an +input with your datepicker, create a template reference for the datepicker and assign it to the +`matDatepicker` attribute on the input: + +```html + + +``` diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts index 4bb98d541480..5663e0526202 100644 --- a/src/lib/datepicker/datepicker.ts +++ b/src/lib/datepicker/datepicker.ts @@ -250,7 +250,7 @@ export class MatDatepicker implements OnDestroy { */ _registerInput(input: MatDatepickerInput): void { if (this._datepickerInput) { - throw Error('An MatDatepicker can only be associated with a single input.'); + throw Error('A MatDatepicker can only be associated with a single input.'); } this._datepickerInput = input; this._inputSubscription = diff --git a/src/material-examples/datepicker-api/datepicker-api-example.ts b/src/material-examples/datepicker-api/datepicker-api-example.ts index cf4ce8ad6778..d023949efac7 100644 --- a/src/material-examples/datepicker-api/datepicker-api-example.ts +++ b/src/material-examples/datepicker-api/datepicker-api-example.ts @@ -1,12 +1,9 @@ import {Component} from '@angular/core'; -/** - * @title Datepicker API - */ +/** @title Datepicker open method */ @Component({ selector: 'datepicker-api-example', templateUrl: 'datepicker-api-example.html', styleUrls: ['datepicker-api-example.css'], }) -export class DatepickerApiExample { -} +export class DatepickerApiExample {} diff --git a/src/material-examples/datepicker-disabled/datepicker-disabled-example.css b/src/material-examples/datepicker-disabled/datepicker-disabled-example.css new file mode 100644 index 000000000000..7432308753e6 --- /dev/null +++ b/src/material-examples/datepicker-disabled/datepicker-disabled-example.css @@ -0,0 +1 @@ +/** No CSS for this example */ diff --git a/src/material-examples/datepicker-disabled/datepicker-disabled-example.html b/src/material-examples/datepicker-disabled/datepicker-disabled-example.html new file mode 100644 index 000000000000..ad3b0755167b --- /dev/null +++ b/src/material-examples/datepicker-disabled/datepicker-disabled-example.html @@ -0,0 +1,23 @@ +

+ + + + + +

+ +

+ + + + + +

+ +

+ + + + + +

diff --git a/src/material-examples/datepicker-disabled/datepicker-disabled-example.ts b/src/material-examples/datepicker-disabled/datepicker-disabled-example.ts new file mode 100644 index 000000000000..3b89fafaf8ae --- /dev/null +++ b/src/material-examples/datepicker-disabled/datepicker-disabled-example.ts @@ -0,0 +1,9 @@ +import {Component} from '@angular/core'; + +/** @title Disabled datepicker */ +@Component({ + selector: 'datepicker-disabled-example', + templateUrl: 'datepicker-disabled-example.html', + styleUrls: ['datepicker-disabled-example.css'], +}) +export class DatepickerDisabledExample {} diff --git a/src/material-examples/datepicker-events/datepicker-events-example.css b/src/material-examples/datepicker-events/datepicker-events-example.css new file mode 100644 index 000000000000..a42e43962f66 --- /dev/null +++ b/src/material-examples/datepicker-events/datepicker-events-example.css @@ -0,0 +1,6 @@ +.example-events { + width: 400px; + height: 200px; + border: 1px solid #555; + overflow: auto; +} diff --git a/src/material-examples/datepicker-events/datepicker-events-example.html b/src/material-examples/datepicker-events/datepicker-events-example.html new file mode 100644 index 000000000000..1935c718218c --- /dev/null +++ b/src/material-examples/datepicker-events/datepicker-events-example.html @@ -0,0 +1,10 @@ + + + + + + +
+
{{e}}
+
diff --git a/src/material-examples/datepicker-events/datepicker-events-example.ts b/src/material-examples/datepicker-events/datepicker-events-example.ts new file mode 100644 index 000000000000..d61bbdb9237b --- /dev/null +++ b/src/material-examples/datepicker-events/datepicker-events-example.ts @@ -0,0 +1,16 @@ +import {Component} from '@angular/core'; +import {MatDatepickerInputEvent} from '@angular/material/datepicker'; + +/** @title Datepicker input and change events */ +@Component({ + selector: 'datepicker-events-example', + templateUrl: 'datepicker-events-example.html', + styleUrls: ['datepicker-events-example.css'], +}) +export class DatepickerEventsExample { + events: string[] = []; + + addEvent(type: string, event: MatDatepickerInputEvent) { + this.events.push(`${type}: ${event.value}`); + } +} diff --git a/src/material-examples/datepicker-filter/datepicker-filter-example.ts b/src/material-examples/datepicker-filter/datepicker-filter-example.ts index a2fe6d13f86b..01ccb8a029d7 100644 --- a/src/material-examples/datepicker-filter/datepicker-filter-example.ts +++ b/src/material-examples/datepicker-filter/datepicker-filter-example.ts @@ -1,8 +1,6 @@ import {Component} from '@angular/core'; -/** - * @title Datepicker Filter - */ +/** @title Datepicker with filter validation */ @Component({ selector: 'datepicker-filter-example', templateUrl: 'datepicker-filter-example.html', diff --git a/src/material-examples/datepicker-formats/datepicker-formats-example.css b/src/material-examples/datepicker-formats/datepicker-formats-example.css new file mode 100644 index 000000000000..7432308753e6 --- /dev/null +++ b/src/material-examples/datepicker-formats/datepicker-formats-example.css @@ -0,0 +1 @@ +/** No CSS for this example */ diff --git a/src/material-examples/datepicker-formats/datepicker-formats-example.html b/src/material-examples/datepicker-formats/datepicker-formats-example.html new file mode 100644 index 000000000000..4868f2dc21ed --- /dev/null +++ b/src/material-examples/datepicker-formats/datepicker-formats-example.html @@ -0,0 +1,5 @@ + + + + + diff --git a/src/material-examples/datepicker-formats/datepicker-formats-example.ts b/src/material-examples/datepicker-formats/datepicker-formats-example.ts new file mode 100644 index 000000000000..03569fc0dfea --- /dev/null +++ b/src/material-examples/datepicker-formats/datepicker-formats-example.ts @@ -0,0 +1,44 @@ +import {Component} from '@angular/core'; +import {FormControl} from '@angular/forms'; +import {MomentDateAdapter} from '@angular/material-moment-adapter'; +import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core'; + +// Depending on whether rollup is used, moment needs to be imported differently. +// Since Moment.js doesn't have a default export, we normally need to import using the `* as` +// syntax. However, rollup creates a synthetic default module and we thus need to import it using +// the `default as` syntax. +import * as _moment from 'moment'; +import {default as _rollupMoment} from 'moment'; +const moment = _rollupMoment || _moment; + +// See the Moment.js docs for the meaning of these formats: +// https://momentjs.com/docs/#/displaying/format/ +export const MY_FORMATS = { + parse: { + dateInput: 'LL', + }, + display: { + dateInput: 'LL', + monthYearLabel: 'MMM YYYY', + dateA11yLabel: 'LL', + monthYearA11yLabel: 'MMMM YYYY', + }, +}; + +/** @title Datepicker with custom formats */ +@Component({ + selector: 'datepicker-formats-example', + templateUrl: 'datepicker-formats-example.html', + styleUrls: ['datepicker-formats-example.css'], + providers: [ + // `MomentDateAdapter` can be automatically provided by importing `MomentDateModule` in your + // application's root module. We provide it at the component level here, due to limitations of + // our example generation script. + {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]}, + + {provide: MAT_DATE_FORMATS, useValue: MY_FORMATS}, + ], +}) +export class DatepickerFormatsExample { + date = new FormControl(moment()); +} diff --git a/src/material-examples/datepicker-locale/datepicker-locale-example.css b/src/material-examples/datepicker-locale/datepicker-locale-example.css new file mode 100644 index 000000000000..7432308753e6 --- /dev/null +++ b/src/material-examples/datepicker-locale/datepicker-locale-example.css @@ -0,0 +1 @@ +/** No CSS for this example */ diff --git a/src/material-examples/datepicker-locale/datepicker-locale-example.html b/src/material-examples/datepicker-locale/datepicker-locale-example.html new file mode 100644 index 000000000000..f92432a48237 --- /dev/null +++ b/src/material-examples/datepicker-locale/datepicker-locale-example.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/material-examples/datepicker-locale/datepicker-locale-example.ts b/src/material-examples/datepicker-locale/datepicker-locale-example.ts new file mode 100644 index 000000000000..c99ee56aba53 --- /dev/null +++ b/src/material-examples/datepicker-locale/datepicker-locale-example.ts @@ -0,0 +1,28 @@ +import {Component} from '@angular/core'; +import {MAT_MOMENT_DATE_FORMATS, MomentDateAdapter} from '@angular/material-moment-adapter'; +import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core'; + +/** @title Datepicker with different locale */ +@Component({ + selector: 'datepicker-locale-example', + templateUrl: 'datepicker-locale-example.html', + styleUrls: ['datepicker-locale-example.css'], + providers: [ + // The locale would typically be provided on the root module of your application. We do it at + // the component level here, due to limitations of our example generation script. + {provide: MAT_DATE_LOCALE, useValue: 'ja-JP'}, + + // `MomentDateAdapter` and `MAT_MOMENT_DATE_FORMATS` can be automatically provided by importing + // `MatMomentDateModule` in your applications root module. We provide it at the component level + // here, due to limitations of our example generation script. + {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]}, + {provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS}, + ], +}) +export class DatepickerLocaleExample { + constructor(private adapter: DateAdapter) {} + + french() { + this.adapter.setLocale('fr'); + } +} diff --git a/src/material-examples/datepicker-min-max/datepicker-min-max-example.ts b/src/material-examples/datepicker-min-max/datepicker-min-max-example.ts index fea707bb1fcb..e90e68b212cd 100644 --- a/src/material-examples/datepicker-min-max/datepicker-min-max-example.ts +++ b/src/material-examples/datepicker-min-max/datepicker-min-max-example.ts @@ -1,8 +1,6 @@ import {Component} from '@angular/core'; -/** - * @title Datepicker Min Max - */ +/** @title Datepicker with min & max validation */ @Component({ selector: 'datepicker-min-max-example', templateUrl: 'datepicker-min-max-example.html', diff --git a/src/material-examples/datepicker-moment/datepicker-moment-example.css b/src/material-examples/datepicker-moment/datepicker-moment-example.css new file mode 100644 index 000000000000..7432308753e6 --- /dev/null +++ b/src/material-examples/datepicker-moment/datepicker-moment-example.css @@ -0,0 +1 @@ +/** No CSS for this example */ diff --git a/src/material-examples/datepicker-moment/datepicker-moment-example.html b/src/material-examples/datepicker-moment/datepicker-moment-example.html new file mode 100644 index 000000000000..a6ae46cc7d2d --- /dev/null +++ b/src/material-examples/datepicker-moment/datepicker-moment-example.html @@ -0,0 +1,5 @@ + + + + + diff --git a/src/material-examples/datepicker-moment/datepicker-moment-example.ts b/src/material-examples/datepicker-moment/datepicker-moment-example.ts new file mode 100644 index 000000000000..7aa9d1b3dc35 --- /dev/null +++ b/src/material-examples/datepicker-moment/datepicker-moment-example.ts @@ -0,0 +1,30 @@ +import {Component} from '@angular/core'; +import {FormControl} from '@angular/forms'; +import {MAT_MOMENT_DATE_FORMATS, MomentDateAdapter} from '@angular/material-moment-adapter'; +import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core'; + +// Depending on whether rollup is used, moment needs to be imported differently. +// Since Moment.js doesn't have a default export, we normally need to import using the `* as` +// syntax. However, rollup creates a synthetic default module and we thus need to import it using +// the `default as` syntax. +import * as _moment from 'moment'; +import {default as _rollupMoment} from 'moment'; +const moment = _rollupMoment || _moment; + +/** @title Datepicker that uses Moment.js dates */ +@Component({ + selector: 'datepicker-moment-example', + templateUrl: 'datepicker-moment-example.html', + styleUrls: ['datepicker-moment-example.css'], + providers: [ + // `MomentDateAdapter` and `MAT_MOMENT_DATE_FORMATS` can be automatically provided by importing + // `MatMomentDateModule` in your applications root module. We provide it at the component level + // here, due to limitations of our example generation script. + {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]}, + {provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS}, + ], +}) +export class DatepickerMomentExample { + // Datepicker takes `Moment` objects instead of `Date` objects. + date = new FormControl(moment([2017, 0, 1])); +} diff --git a/src/material-examples/datepicker-overview/datepicker-overview-example.ts b/src/material-examples/datepicker-overview/datepicker-overview-example.ts index b9dde7ca1d3b..afc1b398425a 100644 --- a/src/material-examples/datepicker-overview/datepicker-overview-example.ts +++ b/src/material-examples/datepicker-overview/datepicker-overview-example.ts @@ -1,8 +1,6 @@ import {Component} from '@angular/core'; -/** - * @title Basic datepicker - */ +/** @title Basic datepicker */ @Component({ selector: 'datepicker-overview-example', templateUrl: 'datepicker-overview-example.html', diff --git a/src/material-examples/datepicker-start-view/datepicker-start-view-example.ts b/src/material-examples/datepicker-start-view/datepicker-start-view-example.ts index cb76dba2a7a2..3477eee61afa 100644 --- a/src/material-examples/datepicker-start-view/datepicker-start-view-example.ts +++ b/src/material-examples/datepicker-start-view/datepicker-start-view-example.ts @@ -1,8 +1,6 @@ import {Component} from '@angular/core'; -/** - * @title Datepicker start date - */ +/** @title Datepicker start date */ @Component({ selector: 'datepicker-start-view-example', templateUrl: 'datepicker-start-view-example.html', diff --git a/src/material-examples/datepicker-touch/datepicker-touch-example.ts b/src/material-examples/datepicker-touch/datepicker-touch-example.ts index df5daa92f54e..68298a63d0ce 100644 --- a/src/material-examples/datepicker-touch/datepicker-touch-example.ts +++ b/src/material-examples/datepicker-touch/datepicker-touch-example.ts @@ -1,12 +1,9 @@ import {Component} from '@angular/core'; -/** - * @title Datepicker Touch - */ +/** @title Datepicker touch UI */ @Component({ selector: 'datepicker-touch-example', templateUrl: 'datepicker-touch-example.html', styleUrls: ['datepicker-touch-example.css'], }) -export class DatepickerTouchExample { -} +export class DatepickerTouchExample {} diff --git a/src/material-examples/datepicker-value/datepicker-value-example.css b/src/material-examples/datepicker-value/datepicker-value-example.css new file mode 100644 index 000000000000..7432308753e6 --- /dev/null +++ b/src/material-examples/datepicker-value/datepicker-value-example.css @@ -0,0 +1 @@ +/** No CSS for this example */ diff --git a/src/material-examples/datepicker-value/datepicker-value-example.html b/src/material-examples/datepicker-value/datepicker-value-example.html new file mode 100644 index 000000000000..fbd5f591d1f1 --- /dev/null +++ b/src/material-examples/datepicker-value/datepicker-value-example.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + diff --git a/src/material-examples/datepicker-value/datepicker-value-example.ts b/src/material-examples/datepicker-value/datepicker-value-example.ts new file mode 100644 index 000000000000..5142d3012bb1 --- /dev/null +++ b/src/material-examples/datepicker-value/datepicker-value-example.ts @@ -0,0 +1,13 @@ +import {Component} from '@angular/core'; +import {FormControl} from '@angular/forms'; + +/** @title Datepicker selected value */ +@Component({ + selector: 'datepicker-value-example', + templateUrl: 'datepicker-value-example.html', + styleUrls: ['datepicker-value-example.css'], +}) +export class DatepickerValueExample { + date = new FormControl(new Date()); + serializedDate = new FormControl((new Date()).toISOString()); +} diff --git a/src/material-examples/example-module.ts b/src/material-examples/example-module.ts index 2add4934cdc6..d24d6ab441c1 100644 --- a/src/material-examples/example-module.ts +++ b/src/material-examples/example-module.ts @@ -30,11 +30,17 @@ import {ChipsInputExample} from './chips-input/chips-input-example'; import {ChipsOverviewExample} from './chips-overview/chips-overview-example'; import {ChipsStackedExample} from './chips-stacked/chips-stacked-example'; import {DatepickerApiExample} from './datepicker-api/datepicker-api-example'; +import {DatepickerDisabledExample} from './datepicker-disabled/datepicker-disabled-example'; +import {DatepickerEventsExample} from './datepicker-events/datepicker-events-example'; import {DatepickerFilterExample} from './datepicker-filter/datepicker-filter-example'; +import {DatepickerFormatsExample} from './datepicker-formats/datepicker-formats-example'; +import {DatepickerLocaleExample} from './datepicker-locale/datepicker-locale-example'; import {DatepickerMinMaxExample} from './datepicker-min-max/datepicker-min-max-example'; +import {DatepickerMomentExample} from './datepicker-moment/datepicker-moment-example'; import {DatepickerOverviewExample} from './datepicker-overview/datepicker-overview-example'; import {DatepickerStartViewExample} from './datepicker-start-view/datepicker-start-view-example'; import {DatepickerTouchExample} from './datepicker-touch/datepicker-touch-example'; +import {DatepickerValueExample} from './datepicker-value/datepicker-value-example'; import {DialogContentExampleDialog,DialogContentExample} from './dialog-content/dialog-content-example'; import {DialogDataExampleDialog,DialogDataExample} from './dialog-data/dialog-data-example'; import {DialogElementsExampleDialog,DialogElementsExample} from './dialog-elements/dialog-elements-example'; @@ -208,41 +214,77 @@ export const EXAMPLE_COMPONENTS = { selectorName: null }, 'datepicker-api': { - title: 'Datepicker API', + title: 'Datepicker open method ', component: DatepickerApiExample, additionalFiles: null, selectorName: null }, + 'datepicker-disabled': { + title: 'Disabled datepicker ', + component: DatepickerDisabledExample, + additionalFiles: null, + selectorName: null + }, + 'datepicker-events': { + title: 'Datepicker input and change events ', + component: DatepickerEventsExample, + additionalFiles: null, + selectorName: null + }, 'datepicker-filter': { - title: 'Datepicker Filter', + title: 'Datepicker with filter validation ', component: DatepickerFilterExample, additionalFiles: null, selectorName: null }, + 'datepicker-formats': { + title: 'Datepicker with custom formats ', + component: DatepickerFormatsExample, + additionalFiles: null, + selectorName: null + }, + 'datepicker-locale': { + title: 'Datepicker with different locale ', + component: DatepickerLocaleExample, + additionalFiles: null, + selectorName: null + }, 'datepicker-min-max': { - title: 'Datepicker Min Max', + title: 'Datepicker with min & max validation ', component: DatepickerMinMaxExample, additionalFiles: null, selectorName: null }, + 'datepicker-moment': { + title: 'Datepicker that uses Moment.js dates ', + component: DatepickerMomentExample, + additionalFiles: null, + selectorName: null + }, 'datepicker-overview': { - title: 'Basic datepicker', + title: 'Basic datepicker ', component: DatepickerOverviewExample, additionalFiles: null, selectorName: null }, 'datepicker-start-view': { - title: 'Datepicker start date', + title: 'Datepicker start date ', component: DatepickerStartViewExample, additionalFiles: null, selectorName: null }, 'datepicker-touch': { - title: 'Datepicker Touch', + title: 'Datepicker touch UI ', component: DatepickerTouchExample, additionalFiles: null, selectorName: null }, + 'datepicker-value': { + title: 'Datepicker selected value ', + component: DatepickerValueExample, + additionalFiles: null, + selectorName: null + }, 'dialog-content': { title: 'Dialog with header, scrollable content and actions', component: DialogContentExample, @@ -514,7 +556,7 @@ export const EXAMPLE_COMPONENTS = { selectorName: null }, 'select-no-ripple': { - title: 'Select with cno option ripple ', + title: 'Select with no option ripple ', component: SelectNoRippleExample, additionalFiles: null, selectorName: null @@ -707,11 +749,17 @@ export const EXAMPLE_LIST = [ ChipsOverviewExample, ChipsStackedExample, DatepickerApiExample, + DatepickerDisabledExample, + DatepickerEventsExample, DatepickerFilterExample, + DatepickerFormatsExample, + DatepickerLocaleExample, DatepickerMinMaxExample, + DatepickerMomentExample, DatepickerOverviewExample, DatepickerStartViewExample, DatepickerTouchExample, + DatepickerValueExample, DialogContentExampleDialog,DialogContentExample, DialogDataExampleDialog,DialogDataExample, DialogElementsExampleDialog,DialogElementsExample, diff --git a/src/material-examples/package.json b/src/material-examples/package.json index 466b289923e1..e27be11e754c 100644 --- a/src/material-examples/package.json +++ b/src/material-examples/package.json @@ -27,7 +27,8 @@ "@angular/core": "0.0.0-NG", "@angular/common": "0.0.0-NG", "@angular/http": "0.0.0-NG", - "@angular/material": "0.0.0-PLACEHOLDER" + "@angular/material": "0.0.0-PLACEHOLDER", + "@angular/material-moment-adapter": "0.0.0-PLACEHOLDER" }, "dependencies": { "tslib": "^1.7.1" diff --git a/src/material-examples/tsconfig-build.json b/src/material-examples/tsconfig-build.json index a800246ead3e..d96880b2124f 100644 --- a/src/material-examples/tsconfig-build.json +++ b/src/material-examples/tsconfig-build.json @@ -2,6 +2,8 @@ // ES2015 since the build process will create FESM bundles using rollup. { "compilerOptions": { + // Needed for Moment.js since it doesn't have a default export. + "allowSyntheticDefaultImports": true, "declaration": true, "stripInternal": false, "experimentalDecorators": true, @@ -22,6 +24,7 @@ "paths": { "@angular/material/*": ["../../dist/packages/material/*/public-api"], "@angular/material": ["../../dist/packages/material/public-api"], + "@angular/material-moment-adapter": ["../../dist/packages/material-moment-adapter/public-api"], "@angular/cdk/*": ["../../dist/packages/cdk/*/public-api"] } }, diff --git a/src/material-examples/tsconfig-es5.json b/src/material-examples/tsconfig-es5.json index 0f6a544d8044..3c4a52e343b1 100644 --- a/src/material-examples/tsconfig-es5.json +++ b/src/material-examples/tsconfig-es5.json @@ -2,6 +2,8 @@ // ES2015 since the build process will create FESM bundles using rollup. { "compilerOptions": { + // Needed for Moment.js since it doesn't have a default export. + "allowSyntheticDefaultImports": true, "declaration": false, "stripInternal": false, "experimentalDecorators": true, @@ -22,6 +24,7 @@ "paths": { "@angular/material/*": ["../../dist/packages/material/*/public-api"], "@angular/material": ["../../dist/packages/material/public-api"], + "@angular/material-moment-adapter": ["../../dist/packages/material-moment-adapter/public-api"], "@angular/cdk/*": ["../../dist/packages/cdk/*/public-api"] } }, diff --git a/src/material-examples/tsconfig.json b/src/material-examples/tsconfig.json index f7f702c1c807..e1156619275c 100644 --- a/src/material-examples/tsconfig.json +++ b/src/material-examples/tsconfig.json @@ -2,12 +2,15 @@ { "extends": "../../tsconfig.json", "compilerOptions": { + // Needed for Moment.js since it doesn't have a default export. + "allowSyntheticDefaultImports": true, "rootDir": "..", "baseUrl": ".", "paths": { "@angular/cdk/*": ["../cdk/*"], "@angular/material/*": ["../lib/*"], - "@angular/material": ["../lib/public-api.ts"] + "@angular/material": ["../lib/public-api.ts"], + "@angular/material-moment-adapter": ["../material-moment-adapter/public-api.ts"] } }, "include": ["./**/*.ts"] diff --git a/tools/gulp/tasks/e2e.ts b/tools/gulp/tasks/e2e.ts index fd77e3f5159a..2b033b4ffa36 100644 --- a/tools/gulp/tasks/e2e.ts +++ b/tools/gulp/tasks/e2e.ts @@ -34,7 +34,12 @@ task('e2e', sequenceTask( /** Task that builds the e2e-app in AOT mode. */ task('e2e-app:build', sequenceTask( 'clean', - ['material:build-release', 'cdk:build-release', 'material-examples:build-release'], + [ + 'material:build-release', + 'cdk:build-release', + 'material-moment-adapter:build-release', + 'material-examples:build-release' + ], ['e2e-app:copy-release', 'e2e-app:copy-assets'], 'e2e-app:build-ts' )); @@ -77,5 +82,6 @@ task('e2e-app:copy-release', () => { copySync(join(releasesDir, 'material'), join(outDir, 'material')); copySync(join(releasesDir, 'cdk'), join(outDir, 'cdk')); copySync(join(releasesDir, 'material-examples'), join(outDir, 'material-examples')); + copySync(join(releasesDir, 'material-moment-adapter'), join(outDir, 'material-moment-adapter')); }); diff --git a/tools/package-tools/rollup-globals.ts b/tools/package-tools/rollup-globals.ts index 93db1bddf4e9..4409759e6ce2 100644 --- a/tools/package-tools/rollup-globals.ts +++ b/tools/package-tools/rollup-globals.ts @@ -45,6 +45,7 @@ export const rollupGlobals = { // Some packages are not really needed for the UMD bundles, but for the missingRollupGlobals rule. '@angular/material-examples': 'ng.materialExamples', '@angular/material': 'ng.material', + '@angular/material-moment-adapter': 'ng.materialMomentAdapter', '@angular/cdk': 'ng.cdk', // Include secondary entry-points of the cdk and material packages From cee2e1a43deed2cf2c68b52d082559a8ed144206 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Tue, 17 Oct 2017 12:28:35 -0700 Subject: [PATCH 3/4] fix e2e --- src/e2e-app/system-config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/e2e-app/system-config.ts b/src/e2e-app/system-config.ts index 3037d29c232c..2e79b7f50120 100644 --- a/src/e2e-app/system-config.ts +++ b/src/e2e-app/system-config.ts @@ -9,6 +9,7 @@ System.config({ map: { 'rxjs': 'node:rxjs', 'main': 'main.js', + 'moment': 'node:moment/min/moment-with-locales.min.js', // Angular specific mappings. '@angular/core': 'node:@angular/core/bundles/core.umd.js', From b43edd8f5c96d1debfe798a4a6d0073a7c647131 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Tue, 17 Oct 2017 16:28:23 -0700 Subject: [PATCH 4/4] address comments --- src/lib/datepicker/datepicker.md | 91 ++++++++++++++------------------ 1 file changed, 39 insertions(+), 52 deletions(-) diff --git a/src/lib/datepicker/datepicker.md b/src/lib/datepicker/datepicker.md index 6be1d7f3f58e..ae93f0197c8e 100644 --- a/src/lib/datepicker/datepicker.md +++ b/src/lib/datepicker/datepicker.md @@ -48,21 +48,21 @@ containing the `startAt` date. ### Setting the selected date -The type of values that the datepicker expects actually depends on the particular `DateAdapter` that -you're using in your app. For example, when using the `NativeDateAdapter` the datepicker expects -`Date` objects, and when using the `MomentDateAdapter` it expects `Moment` objects. You can also -create your own `DateAdapter` that works with whatever date type you want. (For more information -about this, see the section on -[choosing a date implementation](#choosing-a-date-implementation-and-date-format-settings)). - -Depending on the `DateAdapter` you're using, the datepicker may automatically deserialize certain -date formats for you as well. For example, both the `NativeDateAdapter` and `MomentDateAdapter` -allow [ISO 8601](https://tools.ietf.org/html/rfc3339) strings to be passed to the datepicker and +The type of values that the datepicker expects depends on the type of `DateAdapter` provided in your +application. The `NativeDateAdapter`, for example, works directly with plain JavaScript `Date` +objects. When using the `MomentDateAdapter`, however, the values will all be Moment.js instances. +This use of the adapter pattern allows the datepicker component to work with any arbitrary date +representation with a custom `DateAdapter`. +See [_Choosing a date implementation_](#choosing-a-date-implementation-and-date-format-settings) +for more information. + +Depending on the `DateAdapter` being used, the datepicker may automatically deserialize certain date +formats for you as well. For example, both the `NativeDateAdapter` and `MomentDateAdapter` allow +[ISO 8601](https://tools.ietf.org/html/rfc3339) strings to be passed to the datepicker and automatically converted to the proper object type. This can be convenient when binding data directly -from your backend to the datepicker. However, when possible, you should pass the appropriate object -type. The datepicker will not accept date strings formatted in user format such as `"1/2/2017"` as -this is ambiguous and will mean different things depending on the locale of the browser running the -code. +from your backend to the datepicker. However, the datepicker will not accept date strings formatted +in user format such as `"1/2/2017"` as this is ambiguous and will mean different things depending on +the locale of the browser running the code. As with other types of ``, the datepicker works with `@angular/forms` directives such as `formGroup`, `formControl`, `ngModel`, etc. @@ -81,8 +81,8 @@ from advancing the calendar past the `month` or `year` (depending on current vie The second way to add date validation is using the `matDatepickerFilter` property of the datepicker input. This property accepts a function of ` => boolean` (where `` is the date type used by -the datepicker, see section on -[choosing a date implementation](#choosing-a-date-implementation-and-date-format-settings)). +the datepicker, see +[_Choosing a date implementation_](#choosing-a-date-implementation-and-date-format-settings)). A result of `true` indicates that the date is valid and a result of `false` indicates that it is not. Again this will also disable the dates on the calendar that are invalid. However, one important difference between using `matDatepickerFilter` vs using `min` or `max` is that filtering out all @@ -103,9 +103,9 @@ Each validation property has a different error that can be checked: ### Input and change events The input's native `(input)` and `(change)` events will only trigger due to user interaction with -the input element; they will not fire when the user selects a date from the calendar popup. Because -of this limitation, the datepicker input also has support for `(dateInput)` and `(dateChange)` -events. These trigger when the user interacts with either the input or the popup. +the input element; they will not fire when the user selects a date from the calendar popup. +Therefore, the datepicker input also has support for `(dateInput)` and `(dateChange)` events. These +trigger when the user interacts with either the input or the popup. The `(dateInput)` event will fire whenever the value changes due to the user typing or selecting a date from the calendar. The `(dateChange)` event will fire whenever the user finishes typing input @@ -141,11 +141,11 @@ The calendar popup can be programmatically controlled using the `open` and `clos ### Internationalization -In order to support internationalization, the datepicker supports customization of the following -three pieces via injection: - 1. The date implementation that the datepicker accepts. - 2. The display and parse formats used by the datepicker. - 3. The message strings used in the datepicker's UI. +Internationalization of the datepicker is configured via four aspects: + 1. The date locale. + 2. The date implementation that the datepicker accepts. + 3. The display and parse formats used by the datepicker. + 4. The message strings used in the datepicker's UI. #### Setting the locale code @@ -178,6 +178,12 @@ The easiest way to ensure this is just to import one of the pre-made modules: |`MatNativeDateModule`|`Date` |en-US |None |`@angular/material` | |`MatMomentDateModule`|`Moment` |[See project](https://github.com/moment/moment/tree/develop/src/locale)|[Moment.js](https://momentjs.com/)|`@angular/material-moment-adapter`| +*Please note: `MatNativeDateModule` is based off of the functionality available in JavaScript's +native `Date` object, and is thus not suitable for many locales. One of the biggest shortcomings of +the native `Date` object is the inability to set the parse format. We highly recommend using the +`MomentDateAdapter` or a custom `DateAdapter` that works with the formatting/parsing library of your +choice.* + These modules include providers for `DateAdapter` and `MAT_DATE_FORMATS` ```ts @@ -199,22 +205,14 @@ export class MyComponent { } ``` -*Please note: `MatNativeDateModule` is based off of the functionality available in JavaScript's -native `Date` object, and is thus not suitable for many locales. One of the biggest shortcomings of -the native `Date` object is the inability to set the parse format. We highly recommend using the -`MomentDateAdapter` or a custom `DateAdapter` that works with the formatting/parsing library of your -choice.* - -#### Customizing the date implementation - - - -The datepicker does all of its interaction with date objects via the `DateAdapter`. Making the -datepicker work with a different date implementation is as easy as extending `DateAdapter`, and -using your subclass as the provider. You will also want to make sure that the `MAT_DATE_FORMATS` -provided in your app are formats that can be understood by your date implementation. +It is also possible to create your own `DateAdapter` that works with any date format your app +requires. This is accomplished by subclassing `DateAdapter` and providing your subclass as the +`DateAdapter` implementation. You will also want to make sure that the `MAT_DATE_FORMATS` provided +in your app are formats that can be understood by your date implementation. See +[_Customizing the parse and display formats_](#customizing-the-parse-and-display-formats)for more +information about `MAT_DATE_FORMATS`. ```ts @NgModule({ @@ -318,26 +316,15 @@ In year view: | `ALT` + `PAGE_DOWN` | Go to next 10 years | | `ENTER` | Select current month | -### Future work - -Currently the datepicker supports basic date selection functionality. There are more features that -will be added in future iterations, including: - * Support for datetimes (e.g. May 2, 2017 at 12:30pm) and month + year only (e.g. May 2017) - * Support for selecting and displaying date ranges - * Support for custom time zones - * Infinite scrolling through calendar months - * Easier year selection - * Custom views for the calendar popup - ### Troubleshooting #### Error: MatDatepicker: No provider found for DateAdapter/MAT_DATE_FORMATS This error is thrown if you have not provided all of the injectables the datepicker needs to work. The easiest way to resolve this is to import the `MatNativeDateModule` or `MatMomentDateModule` in -your application's root module. See the section on -[choosing a date implementation](#choosing-a-date-implementation-and-date-format-settings)) for more -information. +your application's root module. See +[_Choosing a date implementation_](#choosing-a-date-implementation-and-date-format-settings)) for +more information. #### Error: A MatDatepicker can only be associated with a single input