@@ -15,8 +15,10 @@ import {
1515 InjectionToken ,
1616 Inject ,
1717 Optional ,
18+ OnDestroy ,
1819} from '@angular/core' ;
1920import { Clipboard } from './clipboard' ;
21+ import { PendingCopy } from './pending-copy' ;
2022
2123/** Object that can be used to configure the default options for `CdkCopyToClipboard`. */
2224export interface CdkCopyToClipboardConfig {
@@ -38,7 +40,7 @@ export const CKD_COPY_TO_CLIPBOARD_CONFIG =
3840 '(click)' : 'copy()' ,
3941 }
4042} )
41- export class CdkCopyToClipboard {
43+ export class CdkCopyToClipboard implements OnDestroy {
4244 /** Content to be copied. */
4345 @Input ( 'cdkCopyToClipboard' ) text : string = '' ;
4446
@@ -62,6 +64,15 @@ export class CdkCopyToClipboard {
6264 */
6365 @Output ( 'copied' ) _deprecatedCopied = this . copied ;
6466
67+ /** Copies that are currently being attempted. */
68+ private _pending = new Set < PendingCopy > ( ) ;
69+
70+ /** Whether the directive has been destroyed. */
71+ private _destroyed : boolean ;
72+
73+ /** Timeout for the current copy attempt. */
74+ private _currentTimeout : any ;
75+
6576 constructor (
6677 private _clipboard : Clipboard ,
6778 /**
@@ -81,16 +92,21 @@ export class CdkCopyToClipboard {
8192 if ( attempts > 1 ) {
8293 let remainingAttempts = attempts ;
8394 const pending = this . _clipboard . beginCopy ( this . text ) ;
95+ this . _pending . add ( pending ) ;
96+
8497 const attempt = ( ) => {
8598 const successful = pending . copy ( ) ;
86- if ( ! successful && -- remainingAttempts ) {
99+ if ( ! successful && -- remainingAttempts && ! this . _destroyed ) {
87100 // @breaking -change 10.0.0 Remove null check for `_ngZone`.
88101 if ( this . _ngZone ) {
89- this . _ngZone . runOutsideAngular ( ( ) => setTimeout ( attempt ) ) ;
102+ this . _currentTimeout = this . _ngZone . runOutsideAngular ( ( ) => setTimeout ( attempt , 1 ) ) ;
90103 } else {
91- setTimeout ( attempt ) ;
104+ // We use 1 for the timeout since it's more predictable when flushing in unit tests.
105+ this . _currentTimeout = setTimeout ( attempt , 1 ) ;
92106 }
93107 } else {
108+ this . _currentTimeout = null ;
109+ this . _pending . delete ( pending ) ;
94110 pending . destroy ( ) ;
95111 this . copied . emit ( successful ) ;
96112 }
@@ -100,4 +116,14 @@ export class CdkCopyToClipboard {
100116 this . copied . emit ( this . _clipboard . copy ( this . text ) ) ;
101117 }
102118 }
119+
120+ ngOnDestroy ( ) {
121+ if ( this . _currentTimeout ) {
122+ clearTimeout ( this . _currentTimeout ) ;
123+ }
124+
125+ this . _pending . forEach ( copy => copy . destroy ( ) ) ;
126+ this . _pending . clear ( ) ;
127+ this . _destroyed = true ;
128+ }
103129}
0 commit comments