Commits
Giuseppe Digilio authored a6d29f5a236
1 1 | import { |
2 + | ChangeDetectorRef, |
2 3 | Component, |
3 - | ComponentFactoryResolver, |
4 4 | ComponentRef, |
5 5 | ElementRef, |
6 6 | EventEmitter, |
7 7 | Input, |
8 8 | OnChanges, |
9 9 | OnDestroy, |
10 10 | OnInit, |
11 11 | Output, |
12 12 | SimpleChanges, |
13 13 | ViewChild |
14 14 | } from '@angular/core'; |
15 + | |
16 + | import { Subscription } from 'rxjs'; |
17 + | import { debounceTime, take } from 'rxjs/operators'; |
18 + | |
15 19 | import { ListableObject } from '../listable-object.model'; |
16 20 | import { ViewMode } from '../../../../core/shared/view-mode.model'; |
17 21 | import { Context } from '../../../../core/shared/context.model'; |
18 22 | import { getListableObjectComponent } from './listable-object.decorator'; |
19 23 | import { GenericConstructor } from '../../../../core/shared/generic-constructor'; |
20 24 | import { ListableObjectDirective } from './listable-object.directive'; |
21 25 | import { CollectionElementLinkType } from '../../collection-element-link.type'; |
22 26 | import { hasValue, isNotEmpty } from '../../../empty.util'; |
23 - | import { Subscription } from 'rxjs'; |
24 27 | import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; |
25 - | import { take } from 'rxjs/operators'; |
26 28 | import { ThemeService } from '../../../theme-support/theme.service'; |
27 29 | |
28 30 | @Component({ |
29 31 | selector: 'ds-listable-object-component-loader', |
30 32 | styleUrls: ['./listable-object-component-loader.component.scss'], |
31 33 | templateUrl: './listable-object-component-loader.component.html' |
32 34 | }) |
33 35 | /** |
34 36 | * Component for determining what component to use depending on the item's entity type (dspace.entity.type) |
35 37 | */ |
75 77 | @Input() value: string; |
76 78 | |
77 79 | /** |
78 80 | * Whether or not informational badges (e.g. Private, Withdrawn) should be hidden |
79 81 | */ |
80 82 | @Input() hideBadges = false; |
81 83 | |
82 84 | /** |
83 85 | * Directive hook used to place the dynamic child component |
84 86 | */ |
85 - | @ViewChild(ListableObjectDirective, {static: true}) listableObjectDirective: ListableObjectDirective; |
87 + | @ViewChild(ListableObjectDirective, { static: true }) listableObjectDirective: ListableObjectDirective; |
86 88 | |
87 89 | /** |
88 90 | * View on the badges template, to be passed on to the loaded component (which will place the badges in the desired |
89 91 | * location, or on top if not specified) |
90 92 | */ |
91 93 | @ViewChild('badges', { static: true }) badges: ElementRef; |
92 94 | |
93 95 | /** |
94 96 | * Emit when the listable object has been reloaded. |
95 97 | */ |
113 115 | |
114 116 | /** |
115 117 | * The reference to the dynamic component |
116 118 | */ |
117 119 | protected compRef: ComponentRef<Component>; |
118 120 | |
119 121 | /** |
120 122 | * The list of input and output names for the dynamic component |
121 123 | */ |
122 124 | protected inAndOutputNames: string[] = [ |
123 - | 'object', |
124 - | 'index', |
125 - | 'linkType', |
126 - | 'listID', |
127 - | 'showLabel', |
128 - | 'context', |
129 - | 'viewMode', |
130 - | 'value', |
131 - | 'hideBadges', |
132 - | 'contentChange', |
133 - | ]; |
134 - | |
135 - | constructor( |
136 - | private componentFactoryResolver: ComponentFactoryResolver, |
137 - | private themeService: ThemeService |
138 - | ) { |
125 + | 'object', |
126 + | 'index', |
127 + | 'linkType', |
128 + | 'listID', |
129 + | 'showLabel', |
130 + | 'context', |
131 + | 'viewMode', |
132 + | 'value', |
133 + | 'hideBadges', |
134 + | 'contentChange', |
135 + | ]; |
136 + | |
137 + | constructor(private cdr: ChangeDetectorRef, private themeService: ThemeService) { |
139 138 | } |
140 139 | |
141 140 | /** |
142 141 | * Setup the dynamic child component |
143 142 | */ |
144 143 | ngOnInit(): void { |
145 144 | this.instantiateComponent(this.object); |
146 145 | } |
147 146 | |
148 147 | /** |
159 158 | .filter((subscription) => hasValue(subscription)) |
160 159 | .forEach((subscription) => subscription.unsubscribe()); |
161 160 | } |
162 161 | |
163 162 | private instantiateComponent(object) { |
164 163 | |
165 164 | this.initBadges(); |
166 165 | |
167 166 | const component = this.getComponent(object.getRenderTypes(), this.viewMode, this.context); |
168 167 | |
169 - | const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component); |
170 - | |
171 168 | const viewContainerRef = this.listableObjectDirective.viewContainerRef; |
172 169 | viewContainerRef.clear(); |
173 170 | |
174 171 | this.compRef = viewContainerRef.createComponent( |
175 - | componentFactory, |
176 - | 0, |
177 - | undefined, |
178 - | [ |
179 - | [this.badges.nativeElement], |
180 - | ]); |
172 + | component, { |
173 + | index: 0, |
174 + | injector: undefined, |
175 + | projectableNodes: [ |
176 + | [this.badges.nativeElement], |
177 + | ] |
178 + | } |
179 + | ); |
181 180 | |
182 181 | this.connectInputsAndOutputs(); |
183 182 | |
184 183 | if ((this.compRef.instance as any).reloadedObject) { |
185 - | (this.compRef.instance as any).reloadedObject.pipe(take(1)).subscribe((reloadedObject: DSpaceObject) => { |
184 + | (this.compRef.instance as any).reloadedObject.pipe( |
185 + | // Add delay before emitting event to allow the new object is elaborated on REST side |
186 + | debounceTime((100)), |
187 + | take(1) |
188 + | ).subscribe((reloadedObject: DSpaceObject) => { |
186 189 | if (reloadedObject) { |
187 190 | this.compRef.destroy(); |
188 191 | this.object = reloadedObject; |
189 192 | this.instantiateComponent(reloadedObject); |
190 - | // Add delay before emitting event to allow the new object is instantiated |
191 - | setTimeout(() => { |
192 - | this.contentChange.emit(reloadedObject); |
193 - | }, 100); |
193 + | this.cdr.detectChanges(); |
194 + | this.contentChange.emit(reloadedObject); |
194 195 | } |
195 196 | }); |
196 197 | } |
197 198 | } |
198 199 | |
199 200 | /** |
200 201 | * Initialize which badges should be visible in the listable component |
201 202 | */ |
202 203 | initBadges() { |
203 204 | let objectAsAny = this.object as any; |