Skip to content

Commit 6e29f30

Browse files
108588: Fixed browse by date tab's year dropdown always being empty
- The data passed to the injector in BrowseByComponent was not updated by ngOnChanges - Also refactored the injector logic to StartsWithLoaderComponent
1 parent 6f51bd8 commit 6e29f30

11 files changed

Lines changed: 167 additions & 130 deletions

src/app/browse-by/browse-by-metadata/browse-by-metadata.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export class BrowseByMetadataComponent implements OnInit, OnChanges, OnDestroy {
109109
* The list of StartsWith options
110110
* Should be defined after ngOnInit is called!
111111
*/
112-
startsWithOptions;
112+
startsWithOptions: (string | number)[];
113113

114114
/**
115115
* The value we're browsing items for

src/app/shared/browse-by/browse-by.component.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<ng-container *ngVar="(objects$ | async) as objects">
22
<h1 *ngIf="displayTitle">{{title | translate}}</h1>
3-
<ng-container *ngComponentOutlet="getStartsWithComponent(); injector: objectInjector;"></ng-container>
3+
<ds-starts-with-loader [paginationId]="paginationConfig?.id" [startsWithOptions]="startsWithOptions" [type]="type">
4+
</ds-starts-with-loader>
45
<div *ngIf="objects?.hasSucceeded && !objects?.isLoading && objects?.payload?.page.length > 0" @fadeIn>
56
<div *ngIf="shouldDisplayResetButton$ |async" class="mb-2 reset">
67
<ds-themed-results-back-button [back]="back" [buttonLabel]="buttonLabel"></ds-themed-results-back-button>

src/app/shared/browse-by/browse-by.component.ts

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { Component, EventEmitter, Injector, Input, OnDestroy, OnInit, Output } from '@angular/core';
1+
import { Component, EventEmitter, Injector, Input, OnDestroy, OnInit, Output, OnChanges } from '@angular/core';
22
import { RemoteData } from '../../core/data/remote-data';
33
import { PaginatedList } from '../../core/data/paginated-list.model';
44
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
55
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
66
import { fadeIn, fadeInOut } from '../animations/fade';
77
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs';
88
import { ListableObject } from '../object-collection/shared/listable-object.model';
9-
import { getStartsWithComponent, StartsWithType } from '../starts-with/starts-with-decorator';
9+
import { StartsWithType } from '../starts-with/starts-with-decorator';
1010
import { PaginationService } from '../../core/pagination/pagination.service';
1111
import { ViewMode } from '../../core/shared/view-mode.model';
1212
import { RouteService } from '../../core/services/route.service';
@@ -26,7 +26,7 @@ import { TranslateService } from '@ngx-translate/core';
2626
/**
2727
* Component to display a browse-by page for any ListableObject
2828
*/
29-
export class BrowseByComponent implements OnInit, OnDestroy {
29+
export class BrowseByComponent implements OnInit, OnChanges, OnDestroy {
3030

3131
/**
3232
* ViewMode that should be passed to {@link ListableObjectComponentLoaderComponent}.
@@ -67,7 +67,7 @@ export class BrowseByComponent implements OnInit, OnDestroy {
6767
/**
6868
* The list of options to render for the StartsWith component
6969
*/
70-
@Input() startsWithOptions = [];
70+
@Input() startsWithOptions: (string | number)[] = [];
7171

7272
/**
7373
* Whether or not the pagination should be rendered as simple previous and next buttons instead of the normal pagination
@@ -99,16 +99,6 @@ export class BrowseByComponent implements OnInit, OnDestroy {
9999
*/
100100
@Output() sortDirectionChange = new EventEmitter<SortDirection>();
101101

102-
/**
103-
* An object injector used to inject the startsWithOptions to the switchable StartsWith component
104-
*/
105-
objectInjector: Injector;
106-
107-
/**
108-
* Declare SortDirection enumeration to use it in the template
109-
*/
110-
public sortDirections = SortDirection;
111-
112102
/**
113103
* Observable that tracks if the back button should be displayed based on the path parameters
114104
*/
@@ -142,7 +132,7 @@ export class BrowseByComponent implements OnInit, OnDestroy {
142132
*/
143133
back = () => {
144134
const page = +this.previousPage$.value > 1 ? +this.previousPage$.value : 1;
145-
this.paginationService.updateRoute(this.paginationConfig.id, {page: page}, {[this.paginationConfig.id + '.return']: null, value: null, startsWith: null});
135+
this.paginationService.updateRoute(this.paginationConfig.id, { page: page }, { [this.paginationConfig.id + '.return']: null, value: null, startsWith: null });
146136
};
147137

148138
/**
@@ -159,44 +149,19 @@ export class BrowseByComponent implements OnInit, OnDestroy {
159149
this.next.emit(true);
160150
}
161151

162-
/**
163-
* Change the page size
164-
* @param size
165-
*/
166-
doPageSizeChange(size) {
167-
this.paginationService.updateRoute(this.paginationConfig.id,{pageSize: size});
168-
}
169-
170-
/**
171-
* Change the sort direction
172-
* @param direction
173-
*/
174-
doSortDirectionChange(direction) {
175-
this.paginationService.updateRoute(this.paginationConfig.id,{sortDirection: direction});
176-
}
177-
178-
/**
179-
* Get the switchable StartsWith component dependant on the type
180-
*/
181-
getStartsWithComponent() {
182-
return getStartsWithComponent(this.type);
183-
}
184-
185152
ngOnInit(): void {
186-
this.objectInjector = Injector.create({
187-
providers: [
188-
{ provide: 'startsWithOptions', useFactory: () => (this.startsWithOptions), deps:[] },
189-
{ provide: 'paginationId', useFactory: () => (this.paginationConfig?.id), deps:[] }
190-
],
191-
parent: this.injector
192-
});
193-
194153
const startsWith$ = this.routeService.getQueryParameterValue('startsWith');
195154
const value$ = this.routeService.getQueryParameterValue('value');
196155

197156
this.shouldDisplayResetButton$ = observableCombineLatest([startsWith$, value$]).pipe(
198157
map(([startsWith, value]) => hasValue(startsWith) || hasValue(value))
199158
);
159+
}
160+
161+
ngOnChanges(): void {
162+
if (this.sub) {
163+
this.sub.unsubscribe();
164+
}
200165
this.sub = this.routeService.getQueryParameterValue(this.paginationConfig.id + '.return').subscribe(this.previousPage$);
201166
}
202167

src/app/shared/shared.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ import {
282282
import { BitstreamListItemComponent } from './object-list/bitstream-list-item/bitstream-list-item.component';
283283
import { NgxPaginationModule } from 'ngx-pagination';
284284
import { DynamicComponentLoaderDirective } from './abstract-component-loader/dynamic-component-loader.directive';
285+
import { StartsWithLoaderComponent } from './starts-with/starts-with-loader.component';
285286

286287
const MODULES = [
287288
CommonModule,
@@ -374,7 +375,7 @@ const COMPONENTS = [
374375
ThemedStatusBadgeComponent,
375376
BadgesComponent,
376377
ThemedBadgesComponent,
377-
378+
StartsWithLoaderComponent,
378379
ItemSelectComponent,
379380
CollectionSelectComponent,
380381
MetadataRepresentationLoaderComponent,

src/app/shared/starts-with/date/starts-with-date.component.spec.ts

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ import { CommonModule } from '@angular/common';
33
import { RouterTestingModule } from '@angular/router/testing';
44
import { TranslateModule } from '@ngx-translate/core';
55
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
6-
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
6+
import { ActivatedRoute, Router } from '@angular/router';
77
import { NO_ERRORS_SCHEMA } from '@angular/core';
8-
import { of as observableOf } from 'rxjs';
98
import { By } from '@angular/platform-browser';
109
import { StartsWithDateComponent } from './starts-with-date.component';
1110
import { ActivatedRouteStub } from '../../testing/active-router.stub';
@@ -17,29 +16,25 @@ import { PaginationServiceStub } from '../../testing/pagination-service.stub';
1716
describe('StartsWithDateComponent', () => {
1817
let comp: StartsWithDateComponent;
1918
let fixture: ComponentFixture<StartsWithDateComponent>;
20-
let route: ActivatedRoute;
21-
let router: Router;
22-
let paginationService;
2319

24-
const options = [2019, 2018, 2017, 2016, 2015];
20+
let route: ActivatedRouteStub;
21+
let paginationService: PaginationServiceStub;
22+
let router: RouterStub;
2523

26-
const activatedRouteStub = Object.assign(new ActivatedRouteStub(), {
27-
params: observableOf({}),
28-
queryParams: observableOf({})
29-
});
24+
const options = [2019, 2018, 2017, 2016, 2015];
3025

31-
paginationService = new PaginationServiceStub();
26+
beforeEach(waitForAsync(async () => {
27+
route = new ActivatedRouteStub();
28+
router = new RouterStub();
29+
paginationService = new PaginationServiceStub();
3230

33-
beforeEach(waitForAsync(() => {
34-
TestBed.configureTestingModule({
31+
await TestBed.configureTestingModule({
3532
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
3633
declarations: [StartsWithDateComponent, EnumKeysPipe],
3734
providers: [
38-
{ provide: 'startsWithOptions', useValue: options },
39-
{ provide: 'paginationId', useValue: 'page-id' },
40-
{ provide: ActivatedRoute, useValue: activatedRouteStub },
35+
{ provide: ActivatedRoute, useValue: route },
4136
{ provide: PaginationService, useValue: paginationService },
42-
{ provide: Router, useValue: new RouterStub() }
37+
{ provide: Router, useValue: router },
4338
],
4439
schemas: [NO_ERRORS_SCHEMA]
4540
}).compileComponents();
@@ -48,9 +43,9 @@ describe('StartsWithDateComponent', () => {
4843
beforeEach(() => {
4944
fixture = TestBed.createComponent(StartsWithDateComponent);
5045
comp = fixture.componentInstance;
46+
comp.paginationId = 'page-id';
47+
comp.startsWithOptions = options;
5148
fixture.detectChanges();
52-
route = (comp as any).route;
53-
router = (comp as any).router;
5449
});
5550

5651
it('should create a FormGroup containing a startsWith FormControl', () => {
@@ -156,10 +151,6 @@ describe('StartsWithDateComponent', () => {
156151
describe('when filling in the input form', () => {
157152
let form;
158153
const expectedValue = '2015';
159-
const extras: NavigationExtras = {
160-
queryParams: Object.assign({ startsWith: expectedValue }),
161-
queryParamsHandling: 'merge'
162-
};
163154

164155
beforeEach(() => {
165156
form = fixture.debugElement.query(By.css('form'));

src/app/shared/starts-with/date/starts-with-date.component.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
import { Component, Inject } from '@angular/core';
2-
import { ActivatedRoute, Router } from '@angular/router';
3-
1+
import { Component, OnInit } from '@angular/core';
42
import { renderStartsWithFor, StartsWithType } from '../starts-with-decorator';
53
import { StartsWithAbstractComponent } from '../starts-with-abstract.component';
64
import { hasValue } from '../../empty.util';
7-
import { PaginationService } from '../../../core/pagination/pagination.service';
85

96
/**
107
* A switchable component rendering StartsWith options for the type "Date".
@@ -16,7 +13,7 @@ import { PaginationService } from '../../../core/pagination/pagination.service';
1613
templateUrl: './starts-with-date.component.html'
1714
})
1815
@renderStartsWithFor(StartsWithType.date)
19-
export class StartsWithDateComponent extends StartsWithAbstractComponent {
16+
export class StartsWithDateComponent extends StartsWithAbstractComponent implements OnInit {
2017

2118
/**
2219
* A list of options for months to select from
@@ -33,14 +30,6 @@ export class StartsWithDateComponent extends StartsWithAbstractComponent {
3330
*/
3431
startsWithYear: number;
3532

36-
public constructor(@Inject('startsWithOptions') public startsWithOptions: any[],
37-
@Inject('paginationId') public paginationId: string,
38-
protected paginationService: PaginationService,
39-
protected route: ActivatedRoute,
40-
protected router: Router) {
41-
super(startsWithOptions, paginationId, paginationService, route, router);
42-
}
43-
4433
ngOnInit() {
4534
this.monthOptions = [
4635
'none',
@@ -133,13 +122,6 @@ export class StartsWithDateComponent extends StartsWithAbstractComponent {
133122
}
134123
}
135124

136-
/**
137-
* Get startsWithYear as a number;
138-
*/
139-
getStartsWithYear() {
140-
return this.startsWithYear;
141-
}
142-
143125
/**
144126
* Get startsWithMonth as a number;
145127
*/

src/app/shared/starts-with/starts-with-abstract.component.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
1+
import { Component, OnDestroy, OnInit, Input } from '@angular/core';
22
import { ActivatedRoute, Router } from '@angular/router';
33
import { Subscription } from 'rxjs';
44
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
55
import { hasValue } from '../empty.util';
66
import { PaginationService } from '../../core/pagination/pagination.service';
7+
import { StartsWithType } from './starts-with-decorator';
78

89
/**
910
* An abstract component to render StartsWith options
@@ -13,6 +14,13 @@ import { PaginationService } from '../../core/pagination/pagination.service';
1314
template: ''
1415
})
1516
export abstract class StartsWithAbstractComponent implements OnInit, OnDestroy {
17+
18+
@Input() paginationId: string;
19+
20+
@Input() startsWithOptions: (string | number)[];
21+
22+
@Input() type: StartsWithType;
23+
1624
/**
1725
* The currently selected startsWith in string format
1826
*/
@@ -28,11 +36,11 @@ export abstract class StartsWithAbstractComponent implements OnInit, OnDestroy {
2836
*/
2937
subs: Subscription[] = [];
3038

31-
public constructor(@Inject('startsWithOptions') public startsWithOptions: any[],
32-
@Inject('paginationId') public paginationId: string,
33-
protected paginationService: PaginationService,
34-
protected route: ActivatedRoute,
35-
protected router: Router) {
39+
public constructor(
40+
protected paginationService: PaginationService,
41+
protected route: ActivatedRoute,
42+
protected router: Router,
43+
) {
3644
}
3745

3846
ngOnInit(): void {
@@ -55,15 +63,6 @@ export abstract class StartsWithAbstractComponent implements OnInit, OnDestroy {
5563
return this.startsWith;
5664
}
5765

58-
/**
59-
* Set the startsWith by event
60-
* @param event
61-
*/
62-
setStartsWithEvent(event: Event) {
63-
this.startsWith = (event.target as HTMLInputElement).value;
64-
this.setStartsWithParam();
65-
}
66-
6766
/**
6867
* Set the startsWith by string
6968
* @param startsWith
@@ -82,7 +81,7 @@ export abstract class StartsWithAbstractComponent implements OnInit, OnDestroy {
8281
if (resetPage) {
8382
this.paginationService.updateRoute(this.paginationId, {page: 1}, { startsWith: this.startsWith });
8483
} else {
85-
this.router.navigate([], {
84+
void this.router.navigate([], {
8685
queryParams: Object.assign({ startsWith: this.startsWith }),
8786
queryParamsHandling: 'merge'
8887
});

0 commit comments

Comments
 (0)