11import {
2+ AsyncPipe ,
23 NgClass ,
34 NgForOf ,
45 NgIf ,
@@ -25,12 +26,13 @@ import {
2526 DynamicFormLayoutService ,
2627 DynamicFormValidationService ,
2728} from '@ng-dynamic-forms/core' ;
29+ import { TranslateModule } from '@ngx-translate/core' ;
2830import findKey from 'lodash/findKey' ;
31+ import { BehaviorSubject } from 'rxjs' ;
2932import {
30- EMPTY ,
31- reduce ,
32- } from 'rxjs' ;
33- import { expand } from 'rxjs/operators' ;
33+ map ,
34+ tap ,
35+ } from 'rxjs/operators' ;
3436
3537import { PaginatedList } from '../../../../../../core/data/paginated-list.model' ;
3638import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/shared/operators' ;
@@ -65,6 +67,8 @@ export interface ListItem {
6567 NgbButtonsModule ,
6668 NgForOf ,
6769 ReactiveFormsModule ,
70+ AsyncPipe ,
71+ TranslateModule ,
6872 ] ,
6973 standalone : true ,
7074} )
@@ -78,7 +82,9 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
7882 @Output ( ) focus : EventEmitter < any > = new EventEmitter < any > ( ) ;
7983
8084 public items : ListItem [ ] [ ] = [ ] ;
81- protected optionsList : VocabularyEntry [ ] ;
85+ public showLoadMore$ : BehaviorSubject < boolean > = new BehaviorSubject < boolean > ( false ) ;
86+ protected optionsList : VocabularyEntry [ ] = [ ] ;
87+ private nextPageInfo : PageInfo ;
8288
8389 constructor ( private vocabularyService : VocabularyService ,
8490 private cdr : ChangeDetectorRef ,
@@ -94,7 +100,7 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
94100 */
95101 ngOnInit ( ) {
96102 if ( this . model . vocabularyOptions && hasValue ( this . model . vocabularyOptions . name ) ) {
97- this . setOptionsFromVocabulary ( ) ;
103+ this . initOptionsFromVocabulary ( ) ;
98104 }
99105 }
100106
@@ -141,70 +147,18 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
141147 /**
142148 * Setting up the field options from vocabulary
143149 */
144- protected setOptionsFromVocabulary ( ) {
150+ protected initOptionsFromVocabulary ( ) {
145151 if ( this . model . vocabularyOptions . name && this . model . vocabularyOptions . name . length > 0 ) {
146152 const listGroup = this . group . controls [ this . model . id ] as UntypedFormGroup ;
147153 if ( this . model . repeatable && this . model . required ) {
148154 listGroup . addValidators ( this . hasAtLeastOneVocabularyEntry ( ) ) ;
149155 }
150156
151- const initialPageInfo : PageInfo = new PageInfo ( {
157+ this . nextPageInfo = new PageInfo ( {
152158 elementsPerPage : 20 , currentPage : 1 ,
153159 } as PageInfo ) ;
154160
155- this . vocabularyService . getVocabularyEntries ( this . model . vocabularyOptions , initialPageInfo ) . pipe (
156- getFirstSucceededRemoteDataPayload ( ) ,
157- expand ( ( entries : PaginatedList < VocabularyEntry > ) => {
158- if ( entries . pageInfo . currentPage < entries . pageInfo . totalPages ) {
159- const nextPageInfo : PageInfo = new PageInfo ( {
160- elementsPerPage : 20 , currentPage : entries . pageInfo . currentPage + 1 ,
161- } as PageInfo ) ;
162- return this . vocabularyService . getVocabularyEntries ( this . model . vocabularyOptions , nextPageInfo ) . pipe (
163- getFirstSucceededRemoteDataPayload ( ) ,
164- ) ;
165- } else {
166- return EMPTY ;
167- }
168- } ) ,
169- reduce ( ( acc : VocabularyEntry [ ] , entries : PaginatedList < VocabularyEntry > ) => acc . concat ( entries . page ) , [ ] ) ,
170- ) . subscribe ( ( allEntries : VocabularyEntry [ ] ) => {
171- let groupCounter = 0 ;
172- let itemsPerGroup = 0 ;
173- let tempList : ListItem [ ] = [ ] ;
174- this . optionsList = allEntries ;
175- // Make a list of available options (checkbox/radio) and split in groups of 'model.groupLength'
176- allEntries . forEach ( ( option : VocabularyEntry , key : number ) => {
177- const value = option . authority || option . value ;
178- const checked : boolean = isNotEmpty ( findKey (
179- this . model . value ,
180- ( v ) => v . value === option . value ) ) ;
181-
182- const item : ListItem = {
183- id : `${ this . model . id } _${ value } ` ,
184- label : option . display ,
185- value : checked ,
186- index : key ,
187- } ;
188- if ( this . model . repeatable ) {
189- this . formBuilderService . addFormGroupControl ( listGroup , ( this . model as DynamicListCheckboxGroupModel ) , new DynamicCheckboxModel ( item ) ) ;
190- } else {
191- ( this . model as DynamicListRadioGroupModel ) . options . push ( {
192- label : item . label ,
193- value : option ,
194- } ) ;
195- }
196- tempList . push ( item ) ;
197- itemsPerGroup ++ ;
198- this . items [ groupCounter ] = tempList ;
199- if ( itemsPerGroup === this . model . groupLength ) {
200- groupCounter ++ ;
201- itemsPerGroup = 0 ;
202- tempList = [ ] ;
203- }
204- } ) ;
205- this . cdr . markForCheck ( ) ;
206- } ) ;
207-
161+ this . loadEntries ( listGroup ) ;
208162 }
209163 }
210164
@@ -217,4 +171,70 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
217171 } ;
218172 }
219173
174+ /**
175+ * Update current page state to keep track of which one to load next
176+ * @param response
177+ */
178+ setPaginationInfo ( response : PaginatedList < VocabularyEntry > ) {
179+ if ( response . pageInfo . currentPage < response . pageInfo . totalPages ) {
180+ this . nextPageInfo = Object . assign ( new PageInfo ( ) , response . pageInfo , { currentPage : response . currentPage + 1 } ) ;
181+ this . showLoadMore$ . next ( true ) ;
182+ } else {
183+ this . showLoadMore$ . next ( false ) ;
184+ }
185+ }
186+
187+ /**
188+ * Load entries page
189+ *
190+ * @param listGroup
191+ */
192+ loadEntries ( listGroup ?: UntypedFormGroup ) {
193+ if ( ! hasValue ( listGroup ) ) {
194+ listGroup = this . group . controls [ this . model . id ] as UntypedFormGroup ;
195+ }
196+
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 = [ ] ;
235+ }
236+ } ) ;
237+ this . cdr . markForCheck ( ) ;
238+ } ) ;
239+ }
220240}
0 commit comments