From 69942199acf6cd4b6d8b0561ab53a97816b9247c Mon Sep 17 00:00:00 2001 From: Johannes Hoppe Date: Fri, 19 Nov 2021 10:47:48 +0100 Subject: [PATCH] proof of work: successfully patched date input controls on Safari --- workspace/package-lock.json | 18 +++++++---- workspace/package.json | 2 +- .../projects/date-value-accessor/package.json | 4 ++- .../date-value-accessor-polyfill.module.ts | 8 +++++ .../src/lib/date-value-accessor-polyfill.ts | 30 +++++++++++++++++++ .../date-value-accessor/src/public-api.ts | 3 ++ workspace/projects/demo/.browserslistrc | 2 -- workspace/projects/demo/src/app/app.module.ts | 6 ++-- .../reactive-form.component.html | 6 +++- .../reactive-form/reactive-form.component.ts | 3 ++ .../template-driven-form.component.html | 5 +++- .../template-driven-form.component.ts | 4 +++ .../reactive-form-iso.component.html | 6 +++- .../reactive-form-iso.component.ts | 3 ++ .../template-driven-form-iso.component.html | 5 +++- .../template-driven-form-iso.component.ts | 4 +++ workspace/projects/demo/src/polyfills.ts | 1 - 17 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 workspace/projects/date-value-accessor/src/lib/date-value-accessor-polyfill.module.ts create mode 100644 workspace/projects/date-value-accessor/src/lib/date-value-accessor-polyfill.ts diff --git a/workspace/package-lock.json b/workspace/package-lock.json index d3088f1..962eeb2 100644 --- a/workspace/package-lock.json +++ b/workspace/package-lock.json @@ -4,6 +4,14 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@12core/date-input-polyfill": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@12core/date-input-polyfill/-/date-input-polyfill-3.1.1.tgz", + "integrity": "sha512-07fzWngy8bVXa+k+3gq2gO50mrt0gXuk9BFAa8fy2hPp5RLreZdRpqIXY0aLeZ5Jw6/mVxDi+P8jbzelFPgBug==", + "requires": { + "dateformat": "^4.3.1" + } + }, "@ampproject/remapping": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-1.0.1.tgz", @@ -3449,11 +3457,6 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "configurable-date-input-polyfill": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/configurable-date-input-polyfill/-/configurable-date-input-polyfill-2.7.2.tgz", - "integrity": "sha512-s2kdlrogNwXxbLFOmDxVXbWTKkohF7AuC3LQSb+q6e8gUCd+p/cYsy/m/yTUs1y0Cy/691Yks1aDjFZavB/yhQ==" - }, "connect": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", @@ -3970,6 +3973,11 @@ "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", "dev": true }, + "dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==" + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", diff --git a/workspace/package.json b/workspace/package.json index 9c375d2..2cb9a41 100644 --- a/workspace/package.json +++ b/workspace/package.json @@ -14,6 +14,7 @@ }, "private": true, "dependencies": { + "@12core/date-input-polyfill": "^3.1.1", "@angular/animations": "~13.0.2", "@angular/common": "~13.0.2", "@angular/compiler": "~13.0.2", @@ -22,7 +23,6 @@ "@angular/platform-browser": "~13.0.2", "@angular/platform-browser-dynamic": "~13.0.2", "@angular/router": "~13.0.2", - "configurable-date-input-polyfill": "^2.7.2", "rxjs": "~6.6.0", "tslib": "^2.0.0", "zone.js": "~0.11.4" diff --git a/workspace/projects/date-value-accessor/package.json b/workspace/projects/date-value-accessor/package.json index c03ac85..0c10a42 100644 --- a/workspace/projects/date-value-accessor/package.json +++ b/workspace/projects/date-value-accessor/package.json @@ -29,9 +29,11 @@ "homepage": "https://github.com/johanneshoppe/angular-date-value-accessor", "peerDependencies": { "@angular/common": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0", - "@angular/core": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0" + "@angular/core": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0", + "@12core/date-input-polyfill": "^3.1.1" }, "dependencies": { + "@12core/date-input-polyfill": "^3.1.1", "tslib": "^2.0.0" } } diff --git a/workspace/projects/date-value-accessor/src/lib/date-value-accessor-polyfill.module.ts b/workspace/projects/date-value-accessor/src/lib/date-value-accessor-polyfill.module.ts new file mode 100644 index 0000000..a953d10 --- /dev/null +++ b/workspace/projects/date-value-accessor/src/lib/date-value-accessor-polyfill.module.ts @@ -0,0 +1,8 @@ +import { NgModule } from '@angular/core'; +import { DateValueAccessorPolyfill } from './date-value-accessor-polyfill'; + +@NgModule({ + declarations: [DateValueAccessorPolyfill], + exports: [DateValueAccessorPolyfill] +}) +export class DateValueAccessorPolyfillModule { } diff --git a/workspace/projects/date-value-accessor/src/lib/date-value-accessor-polyfill.ts b/workspace/projects/date-value-accessor/src/lib/date-value-accessor-polyfill.ts new file mode 100644 index 0000000..6672ef7 --- /dev/null +++ b/workspace/projects/date-value-accessor/src/lib/date-value-accessor-polyfill.ts @@ -0,0 +1,30 @@ +import { Directive } from "@angular/core"; +import '@12core/date-input-polyfill/dist/date-input-polyfill.esm'; +import { Input } from '@12core/date-input-polyfill/dist/date-input-polyfill.esm' + + +/** + * The original polyfill patches controls on DOMContentLoaded and body.mousedown + * but not when Angular adds elements to DOM + * see https://github.com/little-core-labs/date-input-polyfill/blob/master/src/date-input-polyfill.js + * + * This directives makes sure all our date input controls are patched before first usage + */ +@Directive({ + selector: '[useValueAsDate],[useValueAsLocalDate],[useValueAsIso],[useValueAsLocalIso]' +}) +export class DateValueAccessorPolyfill { + constructor() { + if (!Input.supportsDateInput()) { + Input.addPickerToDateInputs() + } + } +} + +// https://stackoverflow.com/a/31732310 +export function isSafari() { + return navigator.vendor && navigator.vendor.indexOf('Apple') > -1 && + navigator.userAgent && + navigator.userAgent.indexOf('CriOS') == -1 && + navigator.userAgent.indexOf('FxiOS') == -1; +} diff --git a/workspace/projects/date-value-accessor/src/public-api.ts b/workspace/projects/date-value-accessor/src/public-api.ts index 8bffcc5..ee79306 100644 --- a/workspace/projects/date-value-accessor/src/public-api.ts +++ b/workspace/projects/date-value-accessor/src/public-api.ts @@ -11,3 +11,6 @@ export * from './lib/iso-date-value-accessor'; export * from './lib/iso-date-value-accessor.module'; export * from './lib/local-iso-date-value-accessor'; export * from './lib/local-iso-date-value-accessor.module'; + +export * from './lib/date-value-accessor-polyfill'; +export * from './lib/date-value-accessor-polyfill.module'; diff --git a/workspace/projects/demo/.browserslistrc b/workspace/projects/demo/.browserslistrc index 9da39ea..4f9ac26 100644 --- a/workspace/projects/demo/.browserslistrc +++ b/workspace/projects/demo/.browserslistrc @@ -14,5 +14,3 @@ last 2 Edge major versions last 2 Safari major versions last 2 iOS major versions Firefox ESR -IE 9-10 # Angular support for IE 9-10 has been deprecated and will be removed as of Angular v11. To opt-in, remove the 'not' prefix on this line. -IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. diff --git a/workspace/projects/demo/src/app/app.module.ts b/workspace/projects/demo/src/app/app.module.ts index d83a6c3..5a04b37 100644 --- a/workspace/projects/demo/src/app/app.module.ts +++ b/workspace/projects/demo/src/app/app.module.ts @@ -1,9 +1,10 @@ import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; -import { IsoDateValueAccessorModule } from 'projects/date-value-accessor/src/lib/iso-date-value-accessor.module'; import { DateValueAccessorModule, + DateValueAccessorPolyfillModule, + IsoDateValueAccessorModule, LocalDateValueAccessorModule, LocalIsoDateValueAccessorModule, } from 'projects/date-value-accessor/src/public-api'; @@ -42,7 +43,8 @@ import { ExplanationLocalIsoDateValueAccessorComponent } from './shared/explanat DateValueAccessorModule, LocalDateValueAccessorModule, IsoDateValueAccessorModule, - LocalIsoDateValueAccessorModule + LocalIsoDateValueAccessorModule, + DateValueAccessorPolyfillModule ], bootstrap: [AppComponent] }) diff --git a/workspace/projects/demo/src/app/demo-with-dates/reactive-form/reactive-form.component.html b/workspace/projects/demo/src/app/demo-with-dates/reactive-form/reactive-form.component.html index 0cd6f33..19a852e 100644 --- a/workspace/projects/demo/src/app/demo-with-dates/reactive-form/reactive-form.component.html +++ b/workspace/projects/demo/src/app/demo-with-dates/reactive-form/reactive-form.component.html @@ -68,7 +68,7 @@

LocalDateValueAccessor

-
+

DefaultValueAccessor
(does not work)

@@ -95,3 +95,7 @@

DefaultValueAccessor
(does not work)

typeof(releaseDate): {{ typeof(demoDefault.releaseDate) }}
+ +
+ Sorry, we disabled the demo of Angular's original DefaultValueAccessor on Safari because it causes an error at runtime. +
diff --git a/workspace/projects/demo/src/app/demo-with-dates/reactive-form/reactive-form.component.ts b/workspace/projects/demo/src/app/demo-with-dates/reactive-form/reactive-form.component.ts index 992546e..f6b7d5d 100644 --- a/workspace/projects/demo/src/app/demo-with-dates/reactive-form/reactive-form.component.ts +++ b/workspace/projects/demo/src/app/demo-with-dates/reactive-form/reactive-form.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; +import { isSafari } from 'projects/date-value-accessor/src/public-api'; import { Release } from '../../shared/release'; @@ -17,6 +18,8 @@ export class ReactiveFormComponent implements OnInit { myFormLocalDateValue: FormGroup; myFormDefault: FormGroup; + isSafari = isSafari(); + constructor(private fb: FormBuilder) { this.demoDateValue = new Release('2.0.0', new Date('2020-01-01')); // UTC this.demoLocalDateValue = new Release('3.0.0', new Date(2020, 0, 1)); // with offset diff --git a/workspace/projects/demo/src/app/demo-with-dates/template-driven-form/template-driven-form.component.html b/workspace/projects/demo/src/app/demo-with-dates/template-driven-form/template-driven-form.component.html index 2b2d39a..0ada50c 100644 --- a/workspace/projects/demo/src/app/demo-with-dates/template-driven-form/template-driven-form.component.html +++ b/workspace/projects/demo/src/app/demo-with-dates/template-driven-form/template-driven-form.component.html @@ -72,7 +72,7 @@

LocalDateValueAccessor

-
+

DefaultValueAccessor
(does not work)

@@ -102,3 +102,6 @@

DefaultValueAccessor
(does not work)

+
+ Sorry, we disabled the demo of Angular's original DefaultValueAccessor on Safari because it causes an error at runtime. +
diff --git a/workspace/projects/demo/src/app/demo-with-dates/template-driven-form/template-driven-form.component.ts b/workspace/projects/demo/src/app/demo-with-dates/template-driven-form/template-driven-form.component.ts index 58bffde..2a9dc02 100644 --- a/workspace/projects/demo/src/app/demo-with-dates/template-driven-form/template-driven-form.component.ts +++ b/workspace/projects/demo/src/app/demo-with-dates/template-driven-form/template-driven-form.component.ts @@ -1,4 +1,6 @@ import { Component } from '@angular/core'; +import { isSafari } from 'projects/date-value-accessor/src/public-api'; + import { Release } from '../../shared/release'; @Component({ @@ -15,6 +17,8 @@ export class TemplateDrivenFormComponent { demoLocalDateValueDisabled = false; demoDefaultDisabled = false; + isSafari = isSafari(); + constructor() { this.demoDateValue = new Release('2.0.0', new Date('2020-01-01')); // UTC this.demoLocalDateValue = new Release('3.0.0', new Date(2020, 0, 1)); // with offset diff --git a/workspace/projects/demo/src/app/demo-with-strings/reactive-form-iso/reactive-form-iso.component.html b/workspace/projects/demo/src/app/demo-with-strings/reactive-form-iso/reactive-form-iso.component.html index 47d26e9..5b5b6c2 100644 --- a/workspace/projects/demo/src/app/demo-with-strings/reactive-form-iso/reactive-form-iso.component.html +++ b/workspace/projects/demo/src/app/demo-with-strings/reactive-form-iso/reactive-form-iso.component.html @@ -66,7 +66,7 @@

LocalIsoDateValueAccessor


-
+

DefaultValueAccessor
(does not work)

@@ -93,3 +93,7 @@

DefaultValueAccessor
(does not work)

typeof(releaseDate): {{ typeof(demoIsoDefault.releaseDate) }}
+ +
+ Sorry, we disabled the demo of Angular's original DefaultValueAccessor on Safari because it causes an error at runtime. +
diff --git a/workspace/projects/demo/src/app/demo-with-strings/reactive-form-iso/reactive-form-iso.component.ts b/workspace/projects/demo/src/app/demo-with-strings/reactive-form-iso/reactive-form-iso.component.ts index 6e27d67..ab994a0 100644 --- a/workspace/projects/demo/src/app/demo-with-strings/reactive-form-iso/reactive-form-iso.component.ts +++ b/workspace/projects/demo/src/app/demo-with-strings/reactive-form-iso/reactive-form-iso.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; +import { isSafari } from 'projects/date-value-accessor/src/public-api'; import { ReleaseWithIsoString } from '../../shared/release-with-iso-string'; @@ -17,6 +18,8 @@ export class ReactiveFormIsoComponent implements OnInit { myFormDefault: FormGroup; myFormLocalDateValue: FormGroup; + isSafari = isSafari(); + constructor(private fb: FormBuilder) { this.demoIsoDateValue = new ReleaseWithIsoString('2.0.0', new Date('2020-01-01').toISOString()); // UTC this.demoLocalIsoDateValue = new ReleaseWithIsoString('3.0.0', new Date(2020, 0, 1).toISOString()); // with offset diff --git a/workspace/projects/demo/src/app/demo-with-strings/template-driven-form-iso/template-driven-form-iso.component.html b/workspace/projects/demo/src/app/demo-with-strings/template-driven-form-iso/template-driven-form-iso.component.html index f493321..aa36837 100644 --- a/workspace/projects/demo/src/app/demo-with-strings/template-driven-form-iso/template-driven-form-iso.component.html +++ b/workspace/projects/demo/src/app/demo-with-strings/template-driven-form-iso/template-driven-form-iso.component.html @@ -71,7 +71,7 @@

LocalIsoDateValueAccessor


-
+

DefaultValueAccessor
(does not work)

@@ -101,3 +101,6 @@

DefaultValueAccessor
(does not work)

+
+ Sorry, we disabled the demo of Angular's original DefaultValueAccessor on Safari because it causes an error at runtime. +
diff --git a/workspace/projects/demo/src/app/demo-with-strings/template-driven-form-iso/template-driven-form-iso.component.ts b/workspace/projects/demo/src/app/demo-with-strings/template-driven-form-iso/template-driven-form-iso.component.ts index d27825f..8c3b8d6 100644 --- a/workspace/projects/demo/src/app/demo-with-strings/template-driven-form-iso/template-driven-form-iso.component.ts +++ b/workspace/projects/demo/src/app/demo-with-strings/template-driven-form-iso/template-driven-form-iso.component.ts @@ -1,4 +1,6 @@ import { Component } from '@angular/core'; +import { isSafari } from 'projects/date-value-accessor/src/public-api'; + import { ReleaseWithIsoString } from '../../shared/release-with-iso-string'; @Component({ @@ -15,6 +17,8 @@ export class TemplateDrivenFormIsoComponent { demoLocalIsoDateValueDisabled = false; demoIsoDefaultDisabled = false; + isSafari = isSafari(); + constructor() { this.demoIsoDateValue = new ReleaseWithIsoString('2.0.0', new Date('2020-01-01').toISOString()); // UTC this.demoLocalIsoDateValue = new ReleaseWithIsoString('3.0.0', new Date(2020, 0, 1).toISOString()); // with offset diff --git a/workspace/projects/demo/src/polyfills.ts b/workspace/projects/demo/src/polyfills.ts index 4b2fc8d..dcd18ea 100644 --- a/workspace/projects/demo/src/polyfills.ts +++ b/workspace/projects/demo/src/polyfills.ts @@ -51,4 +51,3 @@ import 'zone.js'; // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS */ -import 'configurable-date-input-polyfill';