77 OnInit ,
88 SimpleChanges ,
99 Renderer2 ,
10- AfterViewInit
10+ AfterViewInit ,
11+ OnDestroy
1112} from '@angular/core' ;
1213import { isAndroid , isIOS } from 'tns-core-modules/platform' ;
1314
@@ -17,10 +18,11 @@ import { Shadow } from './common/shadow';
1718import { Shape , ShapeEnum } from './common/shape.enum' ;
1819import { View } from 'tns-core-modules/ui/page/page' ;
1920import { StackLayout } from 'tns-core-modules/ui/layouts/stack-layout' ;
21+ import { addWeakEventListener , removeWeakEventListener } from "tns-core-modules/ui/core/weak-event-listener" ;
2022declare const android : any ;
2123
2224@Directive ( { selector : '[shadow]' } )
23- export class NativeShadowDirective implements OnInit , OnChanges , AfterViewInit {
25+ export class NativeShadowDirective implements OnInit , OnChanges , AfterViewInit , OnDestroy {
2426 @Input ( ) shadow : string | AndroidData | IOSData ;
2527 @Input ( ) elevation ?: number | string ;
2628 @Input ( ) pressedElevation ?: number | string ;
@@ -43,32 +45,65 @@ export class NativeShadowDirective implements OnInit, OnChanges, AfterViewInit {
4345 private originalNSFn : any ;
4446 private previousNSFn : any ;
4547 private iosShadowRapper : View ;
48+ private eventsBound = false ;
4649
4750 constructor ( private el : ElementRef , private render : Renderer2 ) {
4851 if ( isAndroid ) {
4952 this . originalNSFn = this . el . nativeElement . _redrawNativeBackground ; //always store the original method
5053 }
5154 }
5255
53- ngOnInit ( ) {
54- this . initializeCommonData ( ) ;
55- if ( isAndroid ) {
56- this . initializeAndroidData ( ) ;
57- } else if ( isIOS ) {
58- this . initializeIOSData ( ) ;
59- }
60- if ( this . shadow && ( this . shadow as AndroidData | IOSData ) . elevation ) {
56+ ngOnInit ( ) { // RadListView calls this multiple times for the same view
57+ if ( ! this . initialized ) {
58+ this . initialized = true ;
59+ this . initializeCommonData ( ) ;
6160 if ( isAndroid ) {
62- this . loadFromAndroidData ( this . shadow as AndroidData ) ;
61+ this . initializeAndroidData ( ) ;
6362 } else if ( isIOS ) {
64- this . loadFromIOSData ( this . shadow as IOSData ) ;
63+ this . initializeIOSData ( ) ;
64+ }
65+ if ( this . shadow && ( this . shadow as AndroidData | IOSData ) . elevation ) {
66+ if ( isAndroid ) {
67+ this . loadFromAndroidData ( this . shadow as AndroidData ) ;
68+ } else if ( isIOS ) {
69+ this . loadFromIOSData ( this . shadow as IOSData ) ;
70+ }
6571 }
72+ this . bindEvents ( ) ;
73+ }
74+ }
75+
76+ ngOnDestroy ( ) {
77+ if ( this . initialized ) {
78+ this . unbindEvents ( ) ;
79+ this . initialized = false ;
80+ }
81+ }
82+
83+ // NS ListViews create elements dynamically
84+ // loaded and unloaded are called before angular is "ready"
85+ // https://github.com/NativeScript/nativescript-angular/issues/1221#issuecomment-422813111
86+ // So we ensure we're running loaded/unloaded events outside of angular
87+ bindEvents ( ) {
88+ if ( ! this . eventsBound ) {
89+ addWeakEventListener ( this . el . nativeElement , View . loadedEvent , this . onLoaded , this ) ;
90+ addWeakEventListener ( this . el . nativeElement , View . unloadedEvent , this . onUnloaded , this ) ;
91+ this . eventsBound = true ;
92+ // in some cases, the element is already loaded by time of binding
93+ if ( this . el . nativeElement . isLoaded ) {
94+ this . onLoaded ( ) ;
95+ }
96+ }
97+ }
98+
99+ unbindEvents ( ) {
100+ if ( this . eventsBound ) {
101+ removeWeakEventListener ( this . el . nativeElement , View . loadedEvent , this . onLoaded , this ) ;
102+ removeWeakEventListener ( this . el . nativeElement , View . unloadedEvent , this . onUnloaded , this ) ;
103+ this . eventsBound = false ;
66104 }
67- this . applyShadow ( ) ;
68- this . initialized = true ;
69105 }
70106
71- @HostListener ( 'loaded' )
72107 onLoaded ( ) {
73108 this . loaded = true ;
74109 // Weirdly ngOnInit isn't called on iOS on demo app
@@ -104,7 +139,6 @@ export class NativeShadowDirective implements OnInit, OnChanges, AfterViewInit {
104139 }
105140 }
106141
107- @HostListener ( 'unloaded' )
108142 onUnloaded ( ) {
109143 this . loaded = false ;
110144
0 commit comments