@@ -3,18 +3,19 @@ import {
33 ComponentFactoryResolver ,
44 EventEmitter ,
55 Input ,
6- OnDestroy ,
76 OnInit ,
87 Output ,
9- ViewChild
8+ ViewChild ,
9+ OnChanges ,
10+ SimpleChanges ,
11+ ComponentRef ,
1012} from '@angular/core' ;
1113import { getComponentByWorkflowTaskOption } from './claimed-task-actions-decorator' ;
1214import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model' ;
1315import { ClaimedTaskActionsDirective } from './claimed-task-actions.directive' ;
14- import { ClaimedTaskActionsAbstractComponent } from '../abstract/claimed-task-actions-abstract.component' ;
15- import { hasValue } from '../../../empty.util' ;
16- import { Subscription } from 'rxjs' ;
16+ import { hasValue , isNotEmpty , hasNoValue } from '../../../empty.util' ;
1717import { MyDSpaceActionsResult } from '../../mydspace-actions' ;
18+ import { ClaimedTaskActionsAbstractComponent } from '../abstract/claimed-task-actions-abstract.component' ;
1819
1920@Component ( {
2021 selector : 'ds-claimed-task-actions-loader' ,
@@ -24,7 +25,7 @@ import { MyDSpaceActionsResult } from '../../mydspace-actions';
2425 * Component for loading a ClaimedTaskAction component depending on the "option" input
2526 * Passes on the ClaimedTask to the component and subscribes to the processCompleted output
2627 */
27- export class ClaimedTaskActionsLoaderComponent implements OnInit , OnDestroy {
28+ export class ClaimedTaskActionsLoaderComponent implements OnInit , OnChanges {
2829 /**
2930 * The ClaimedTask object
3031 */
@@ -47,10 +48,18 @@ export class ClaimedTaskActionsLoaderComponent implements OnInit, OnDestroy {
4748 @ViewChild ( ClaimedTaskActionsDirective , { static : true } ) claimedTaskActionsDirective : ClaimedTaskActionsDirective ;
4849
4950 /**
50- * Array to track all subscriptions and unsubscribe them onDestroy
51- * @type {Array }
51+ * The reference to the dynamic component
5252 */
53- protected subs : Subscription [ ] = [ ] ;
53+ protected compRef : ComponentRef < Component > ;
54+
55+ /**
56+ * The list of input and output names for the dynamic component
57+ */
58+ protected inAndOutputNames : ( keyof ClaimedTaskActionsAbstractComponent & keyof this) [ ] = [
59+ 'object' ,
60+ 'option' ,
61+ 'processCompleted' ,
62+ ] ;
5463
5564 constructor ( private componentFactoryResolver : ComponentFactoryResolver ) {
5665 }
@@ -59,19 +68,42 @@ export class ClaimedTaskActionsLoaderComponent implements OnInit, OnDestroy {
5968 * Fetch, create and initialize the relevant component
6069 */
6170 ngOnInit ( ) : void {
71+ this . instantiateComponent ( ) ;
72+ }
73+
74+ /**
75+ * Whenever the inputs change, update the inputs of the dynamic component
76+ */
77+ ngOnChanges ( changes : SimpleChanges ) : void {
78+ if ( hasNoValue ( this . compRef ) ) {
79+ // sometimes the component has not been initialized yet, so it first needs to be initialized
80+ // before being called again
81+ this . instantiateComponent ( changes ) ;
82+ } else {
83+ // if an input or output has changed
84+ if ( this . inAndOutputNames . some ( ( name : any ) => hasValue ( changes [ name ] ) ) ) {
85+ this . connectInputsAndOutputs ( ) ;
86+ if ( this . compRef ?. instance && 'ngOnChanges' in this . compRef . instance ) {
87+ ( this . compRef . instance as any ) . ngOnChanges ( changes ) ;
88+ }
89+ }
90+ }
91+ }
6292
93+ private instantiateComponent ( changes ?: SimpleChanges ) : void {
6394 const comp = this . getComponentByWorkflowTaskOption ( this . option ) ;
6495 if ( hasValue ( comp ) ) {
6596 const componentFactory = this . componentFactoryResolver . resolveComponentFactory ( comp ) ;
6697
6798 const viewContainerRef = this . claimedTaskActionsDirective . viewContainerRef ;
6899 viewContainerRef . clear ( ) ;
69100
70- const componentRef = viewContainerRef . createComponent ( componentFactory ) ;
71- const componentInstance = ( componentRef . instance as ClaimedTaskActionsAbstractComponent ) ;
72- componentInstance . object = this . object ;
73- if ( hasValue ( componentInstance . processCompleted ) ) {
74- this . subs . push ( componentInstance . processCompleted . subscribe ( ( result ) => this . processCompleted . emit ( result ) ) ) ;
101+ this . compRef = viewContainerRef . createComponent ( componentFactory ) ;
102+
103+ if ( hasValue ( changes ) ) {
104+ this . ngOnChanges ( changes ) ;
105+ } else {
106+ this . connectInputsAndOutputs ( ) ;
75107 }
76108 }
77109 }
@@ -81,11 +113,14 @@ export class ClaimedTaskActionsLoaderComponent implements OnInit, OnDestroy {
81113 }
82114
83115 /**
84- * Unsubscribe from open subscriptions
116+ * Connect the in and outputs of this component to the dynamic component,
117+ * to ensure they're in sync
85118 */
86- ngOnDestroy ( ) : void {
87- this . subs
88- . filter ( ( subscription ) => hasValue ( subscription ) )
89- . forEach ( ( subscription ) => subscription . unsubscribe ( ) ) ;
119+ protected connectInputsAndOutputs ( ) : void {
120+ if ( isNotEmpty ( this . inAndOutputNames ) && hasValue ( this . compRef ) && hasValue ( this . compRef . instance ) ) {
121+ this . inAndOutputNames . filter ( ( name : any ) => this [ name ] !== undefined ) . forEach ( ( name : any ) => {
122+ this . compRef . instance [ name ] = this [ name ] ;
123+ } ) ;
124+ }
90125 }
91126}
0 commit comments