99 Component ,
1010 EventEmitter ,
1111 Input ,
12+ OnDestroy ,
1213 OnInit ,
1314 Output ,
1415} from '@angular/core' ;
@@ -28,7 +29,10 @@ import {
2829} from '@ng-dynamic-forms/core' ;
2930import { TranslateModule } from '@ngx-translate/core' ;
3031import findKey from 'lodash/findKey' ;
31- import { BehaviorSubject } from 'rxjs' ;
32+ import {
33+ BehaviorSubject ,
34+ Subscription ,
35+ } from 'rxjs' ;
3236import {
3337 map ,
3438 tap ,
@@ -43,6 +47,7 @@ import {
4347 hasValue ,
4448 isNotEmpty ,
4549} from '../../../../../empty.util' ;
50+ import { ThemedLoadingComponent } from '../../../../../loading/themed-loading.component' ;
4651import { FormBuilderService } from '../../../form-builder.service' ;
4752import { DynamicListCheckboxGroupModel } from './dynamic-list-checkbox-group.model' ;
4853import { DynamicListRadioGroupModel } from './dynamic-list-radio-group.model' ;
@@ -69,10 +74,11 @@ export interface ListItem {
6974 ReactiveFormsModule ,
7075 AsyncPipe ,
7176 TranslateModule ,
77+ ThemedLoadingComponent ,
7278 ] ,
7379 standalone : true ,
7480} )
75- export class DsDynamicListComponent extends DynamicFormControlComponent implements OnInit {
81+ export class DsDynamicListComponent extends DynamicFormControlComponent implements OnInit , OnDestroy {
7682
7783 @Input ( ) group : UntypedFormGroup ;
7884 @Input ( ) model : any ;
@@ -82,9 +88,10 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
8288 @Output ( ) focus : EventEmitter < any > = new EventEmitter < any > ( ) ;
8389
8490 public items : ListItem [ ] [ ] = [ ] ;
85- public showLoadMore $ : BehaviorSubject < boolean > = new BehaviorSubject < boolean > ( false ) ;
91+ public isLoading $ : BehaviorSubject < boolean > = new BehaviorSubject < boolean > ( true ) ;
8692 protected optionsList : VocabularyEntry [ ] = [ ] ;
8793 private nextPageInfo : PageInfo ;
94+ private subs : Subscription [ ] = [ ] ;
8895
8996 constructor ( private vocabularyService : VocabularyService ,
9097 private cdr : ChangeDetectorRef ,
@@ -104,6 +111,12 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
104111 }
105112 }
106113
114+ ngOnDestroy ( ) {
115+ if ( this . subs . length > 0 ) {
116+ this . subs . forEach ( sub => sub . unsubscribe ( ) ) ;
117+ }
118+ }
119+
107120 /**
108121 * Emits a blur event containing a given value.
109122 * @param event The value to emit.
@@ -178,9 +191,9 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
178191 setPaginationInfo ( response : PaginatedList < VocabularyEntry > ) {
179192 if ( response . pageInfo . currentPage < response . pageInfo . totalPages ) {
180193 this . nextPageInfo = Object . assign ( new PageInfo ( ) , response . pageInfo , { currentPage : response . currentPage + 1 } ) ;
181- this . showLoadMore $. next ( true ) ;
194+ this . isLoading $. next ( true ) ;
182195 } else {
183- this . showLoadMore $. next ( false ) ;
196+ this . isLoading $. next ( false ) ;
184197 }
185198 }
186199
@@ -194,47 +207,53 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
194207 listGroup = this . group . controls [ this . model . id ] as UntypedFormGroup ;
195208 }
196209
197- this . vocabularyService . getVocabularyEntries ( this . model . vocabularyOptions , this . nextPageInfo ) . pipe (
198- getFirstSucceededRemoteDataPayload ( ) ,
199- tap ( ( response ) => this . setPaginationInfo ( response ) ) ,
200- map ( entries => entries . page ) ,
201- ) . subscribe ( ( allEntries : VocabularyEntry [ ] ) => {
202- this . optionsList = [ ...this . optionsList , ...allEntries ] ;
203- let groupCounter = ( this . items . length > 0 ) ? ( this . items . length - 1 ) : 0 ;
204- let itemsPerGroup = 0 ;
205- let tempList : ListItem [ ] = [ ] ;
206-
207- // Make a list of available options (checkbox/radio) and split in groups of 'model.groupLength'
208- allEntries . forEach ( ( option : VocabularyEntry , key : number ) => {
209- const value = option . authority || option . value ;
210- const checked : boolean = isNotEmpty ( findKey (
211- this . model . value ,
212- ( v ) => v ?. value === option . value ) ) ;
213-
214- const item : ListItem = {
215- id : `${ this . model . id } _${ value } ` ,
216- label : option . display ,
217- value : checked ,
218- index : key ,
219- } ;
220- if ( this . model . repeatable ) {
221- this . formBuilderService . addFormGroupControl ( listGroup , ( this . model as DynamicListCheckboxGroupModel ) , new DynamicCheckboxModel ( item ) ) ;
222- } else {
223- ( this . model as DynamicListRadioGroupModel ) . options . push ( {
224- label : item . label ,
225- value : option ,
226- } ) ;
227- }
228- tempList . push ( item ) ;
229- itemsPerGroup ++ ;
230- this . items [ groupCounter ] = tempList ;
231- if ( itemsPerGroup === this . model . groupLength ) {
232- groupCounter ++ ;
233- itemsPerGroup = 0 ;
234- tempList = [ ] ;
210+ this . subs . push (
211+ this . vocabularyService . getVocabularyEntries ( this . model . vocabularyOptions , this . nextPageInfo ) . pipe (
212+ getFirstSucceededRemoteDataPayload ( ) ,
213+ tap ( ( response ) => this . setPaginationInfo ( response ) ) ,
214+ map ( entries => entries . page ) ,
215+ ) . subscribe ( ( allEntries : VocabularyEntry [ ] ) => {
216+ this . optionsList = [ ...this . optionsList , ...allEntries ] ;
217+ let groupCounter = this . items . length ;
218+ let itemsPerGroup = 0 ;
219+ let tempList : ListItem [ ] = [ ] ;
220+
221+ // Make a list of available options (checkbox/radio) and split in groups of 'model.groupLength'
222+ allEntries . forEach ( ( option : VocabularyEntry ) => {
223+ const value = option . authority || option . value ;
224+ const checked : boolean = isNotEmpty ( findKey (
225+ this . model . value ,
226+ ( v ) => v ?. value === option . value ) ) ;
227+
228+ const item : ListItem = {
229+ id : `${ this . model . id } _${ value } ` ,
230+ label : option . display ,
231+ value : checked ,
232+ index : this . optionsList . indexOf ( option ) ,
233+ } ;
234+ if ( this . model . repeatable ) {
235+ this . formBuilderService . addFormGroupControl ( listGroup , ( this . model as DynamicListCheckboxGroupModel ) , new DynamicCheckboxModel ( item ) ) ;
236+ } else {
237+ ( this . model as DynamicListRadioGroupModel ) . options . push ( {
238+ label : item . label ,
239+ value : option ,
240+ } ) ;
241+ }
242+ tempList . push ( item ) ;
243+ itemsPerGroup ++ ;
244+ this . items [ groupCounter ] = tempList ;
245+ if ( itemsPerGroup === this . model . groupLength ) {
246+ groupCounter ++ ;
247+ itemsPerGroup = 0 ;
248+ tempList = [ ] ;
249+ }
250+ } ) ;
251+ this . cdr . markForCheck ( ) ;
252+ // If the paginated request did not reach the end keep loading the entries in the background
253+ if ( this . isLoading$ . value ) {
254+ this . loadEntries ( ) ;
235255 }
236- } ) ;
237- this . cdr . markForCheck ( ) ;
238- } ) ;
256+ } ) ,
257+ ) ;
239258 }
240259}
0 commit comments