Skip to content

Commit 558295b

Browse files
crisbetommalerba
authored andcommitted
fix(popover-edit): rework host listeners to account for changes in Ivy (#16060)
Switches all of the inherited event listeners in `popover-edit` to use `@HostListener`. In Ivy the `host` objects are merged when inheriting, whereas in ViewEngine they are overwritten. This means that with the current setup we'll end up with double event listeners once Ivy lands.
1 parent 59fc0cb commit 558295b

File tree

4 files changed

+50
-19
lines changed

4 files changed

+50
-19
lines changed

src/cdk-experimental/popover-edit/lens-directives.ts

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {ReplaySubject} from 'rxjs';
10-
import {Directive, ElementRef, EventEmitter, OnDestroy, OnInit} from '@angular/core';
10+
import {Directive, ElementRef, EventEmitter, OnDestroy, OnInit, HostListener} from '@angular/core';
1111
import {EDIT_PANE_SELECTOR} from './constants';
1212
import {closest} from './polyfill';
1313
import {EditRef} from './edit-ref';
@@ -23,13 +23,6 @@ export type PopoverEditClickOutBehavior = 'close' | 'submit' | 'noop';
2323
*/
2424
@Directive({
2525
selector: 'form[cdkEditControl]',
26-
host: {
27-
'(ngSubmit)': 'handleFormSubmit()',
28-
'(keydown.enter)': 'editRef.trackEnterPressForClose(true)',
29-
'(keyup.enter)': 'editRef.trackEnterPressForClose(false)',
30-
'(keyup.escape)': 'close()',
31-
'(document:click)': 'handlePossibleClickOut($event)',
32-
},
3326
inputs: [
3427
'clickOutBehavior: cdkEditControlClickOutBehavior',
3528
'preservedFormValue: cdkEditControlPreservedFormValue',
@@ -79,6 +72,11 @@ export class CdkEditControl<FormValue> implements OnDestroy, OnInit {
7972
* the form for validity before proceeding.
8073
* Updates the revert state with the latest submitted value then closes the edit.
8174
*/
75+
// In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
76+
// to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
77+
// can move this back into `host`.
78+
// tslint:disable:no-host-decorator-in-concrete
79+
@HostListener('ngSubmit')
8280
handleFormSubmit(): void {
8381
if (this.ignoreSubmitUnlessValid && !this.editRef.isValid()) { return; }
8482

@@ -97,6 +95,11 @@ export class CdkEditControl<FormValue> implements OnDestroy, OnInit {
9795
* Called on click anywhere in the document.
9896
* If the click was outside of the lens, trigger the specified click out behavior.
9997
*/
98+
// In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
99+
// to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
100+
// can move this back into `host`.
101+
// tslint:disable:no-host-decorator-in-concrete
102+
@HostListener('document:click', ['$event'])
100103
handlePossibleClickOut(evt: Event): void {
101104
if (closest(evt.target, EDIT_PANE_SELECTOR)) { return; }
102105

@@ -113,6 +116,29 @@ export class CdkEditControl<FormValue> implements OnDestroy, OnInit {
113116
}
114117
}
115118

119+
// In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
120+
// to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
121+
// can move this back into `host`.
122+
// tslint:disable:no-host-decorator-in-concrete
123+
@HostListener('keydown')
124+
_handleKeydown() {
125+
this.editRef.trackEnterPressForClose(true);
126+
}
127+
128+
// In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
129+
// to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
130+
// can move this back into `host`.
131+
// tslint:disable:no-host-decorator-in-concrete
132+
@HostListener('keyup', ['$event'])
133+
_handleKeyup(event: KeyboardEvent) {
134+
// TODO(crisbeto): should use cdk/keycodes once the tests are reworked to use cdk/testing.
135+
if (event.key === 'Enter') {
136+
this.editRef.trackEnterPressForClose(false);
137+
} else if (event.key === 'Escape') {
138+
this.close();
139+
}
140+
}
141+
116142
/** Triggers submit on tab out if clickOutBehavior is 'submit'. */
117143
private _handleBlur(): void {
118144
if (this.clickOutBehavior === 'submit') {
@@ -130,14 +156,18 @@ export class CdkEditControl<FormValue> implements OnDestroy, OnInit {
130156
@Directive({
131157
selector: 'button[cdkEditRevert]',
132158
host: {
133-
'(click)': 'revertEdit()',
134159
'type': 'button', // Prevents accidental form submits.
135160
}
136161
})
137162
export class CdkEditRevert<FormValue> {
138163
constructor(
139164
protected readonly editRef: EditRef<FormValue>) {}
140165

166+
// In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
167+
// to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
168+
// can move this back into `host`.
169+
// tslint:disable:no-host-decorator-in-concrete
170+
@HostListener('click')
141171
revertEdit(): void {
142172
this.editRef.reset();
143173
}
@@ -147,14 +177,18 @@ export class CdkEditRevert<FormValue> {
147177
@Directive({
148178
selector: 'button[cdkEditClose]',
149179
host: {
150-
'(click)': 'closeEdit()',
151180
'type': 'button', // Prevents accidental form submits.
152181
}
153182
})
154183
export class CdkEditClose<FormValue> {
155184
constructor(
156185
protected readonly editRef: EditRef<FormValue>) {}
157186

187+
// In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
188+
// to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
189+
// can move this back into `host`.
190+
// tslint:disable:no-host-decorator-in-concrete
191+
@HostListener('click')
158192
closeEdit(): void {
159193
this.editRef.closeAfterEnterKeypress();
160194
}

src/cdk-experimental/popover-edit/table-directives.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
OnDestroy,
1818
TemplateRef,
1919
ViewContainerRef,
20+
HostListener,
2021
} from '@angular/core';
2122
import {fromEvent, merge, ReplaySubject} from 'rxjs';
2223
import {debounceTime, filter, map, mapTo, startWith, takeUntil} from 'rxjs/operators';
@@ -393,7 +394,6 @@ export class CdkRowHoverContent implements AfterViewInit, OnDestroy {
393394
*/
394395
@Directive({
395396
selector: '[cdkEditOpen]',
396-
host: {'(click)': 'openEdit($event)'}
397397
})
398398
export class CdkEditOpen {
399399
constructor(
@@ -408,6 +408,11 @@ export class CdkEditOpen {
408408
}
409409
}
410410

411+
// In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
412+
// to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
413+
// can move this back into `host`.
414+
// tslint:disable:no-host-decorator-in-concrete
415+
@HostListener('click', ['$event'])
411416
openEdit(evt: Event): void {
412417
this.editEventDispatcher.editing.next(closest(this.elementRef.nativeElement!, CELL_SELECTOR));
413418
evt.stopPropagation();

src/material-experimental/popover-edit/lens-directives.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@ import {
2424
@Directive({
2525
selector: 'form[matEditLens]',
2626
host: {
27-
'(ngSubmit)': 'handleFormSubmit()',
28-
'(keydown.enter)': 'editRef.trackEnterPressForClose(true)',
29-
'(keyup.enter)': 'editRef.trackEnterPressForClose(false)',
30-
'(keyup.escape)': 'close()',
31-
'(document:click)': 'handlePossibleClickOut($event)',
3227
'class': 'mat-edit-lens',
3328
},
3429
inputs: [
@@ -46,7 +41,6 @@ export class MatEditLens<FormValue> extends CdkEditControl<FormValue> {
4641
@Directive({
4742
selector: 'button[matEditRevert]',
4843
host: {
49-
'(click)': 'revertEdit()',
5044
'type': 'button', // Prevents accidental form submits.
5145
}
5246
})
@@ -57,7 +51,6 @@ export class MatEditRevert<FormValue> extends CdkEditRevert<FormValue> {
5751
@Directive({
5852
selector: 'button[matEditClose]',
5953
host: {
60-
'(click)': 'closeEdit()',
6154
'type': 'button', // Prevents accidental form submits.
6255
}
6356
})

src/material-experimental/popover-edit/table-directives.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ export class MatRowHoverContent extends CdkRowHoverContent {
107107
*/
108108
@Directive({
109109
selector: '[matEditOpen]',
110-
host: {'(click)': 'openEdit($event)'}
111110
})
112111
export class MatEditOpen extends CdkEditOpen {
113112
}

0 commit comments

Comments
 (0)