@yuuvis/client-framework 3.22.1 → 3.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/yuuvis-client-framework-forms.mjs +403 -19
- package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-metadata-form.mjs +8 -6
- package/fesm2022/yuuvis-client-framework-metadata-form.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-object-form.mjs +27 -4
- package/fesm2022/yuuvis-client-framework-object-form.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-query-list.mjs +144 -69
- package/fesm2022/yuuvis-client-framework-query-list.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-smart-search.mjs +35 -3
- package/fesm2022/yuuvis-client-framework-smart-search.mjs.map +1 -1
- package/lib/assets/i18n/de.json +2 -0
- package/lib/assets/i18n/en.json +2 -0
- package/package.json +5 -5
- package/types/yuuvis-client-framework-forms.d.ts +135 -4
- package/types/yuuvis-client-framework-query-list.d.ts +20 -12
package/lib/assets/i18n/de.json
CHANGED
|
@@ -175,6 +175,7 @@
|
|
|
175
175
|
"yuv.smart-search.combinator.and": "UND",
|
|
176
176
|
"yuv.smart-search.combinator.as-well-as": "sowie",
|
|
177
177
|
"yuv.smart-search.combinator.or": "ODER",
|
|
178
|
+
"yuv.smart-search.condition.dynamic-aria": "Auszufüllendes Feld: {{label}}",
|
|
178
179
|
"yuv.smart-search.condition.edit-aria": "Bedingung bearbeiten: {{label}}",
|
|
179
180
|
"yuv.smart-search.condition.mark-dynamic": "Als auszufüllendes Feld festlegen",
|
|
180
181
|
"yuv.smart-search.condition.remove": "Bedingung entfernen",
|
|
@@ -206,6 +207,7 @@
|
|
|
206
207
|
"yuv.smart-search.operator.like": "ähnlich",
|
|
207
208
|
"yuv.smart-search.operator.not-empty": "ist nicht leer",
|
|
208
209
|
"yuv.smart-search.operator.select": "Operator auswählen…",
|
|
210
|
+
"yuv.smart-search.type.add-type.tooltip": "Typ hinzufügen",
|
|
209
211
|
"yuv.smart-search.type.confirm": "Typen bestätigen",
|
|
210
212
|
"yuv.smart-search.type.remove": "Typ entfernen",
|
|
211
213
|
"yuv.smart-search.type.remove-draft": "Ausgewählten Typ entfernen",
|
package/lib/assets/i18n/en.json
CHANGED
|
@@ -175,6 +175,7 @@
|
|
|
175
175
|
"yuv.smart-search.combinator.and": "AND",
|
|
176
176
|
"yuv.smart-search.combinator.as-well-as": "as well as",
|
|
177
177
|
"yuv.smart-search.combinator.or": "OR",
|
|
178
|
+
"yuv.smart-search.condition.dynamic-aria": "Input field: {{label}}",
|
|
178
179
|
"yuv.smart-search.condition.edit-aria": "Edit condition: {{label}}",
|
|
179
180
|
"yuv.smart-search.condition.mark-dynamic": "Make this an input field",
|
|
180
181
|
"yuv.smart-search.condition.remove": "Remove condition",
|
|
@@ -206,6 +207,7 @@
|
|
|
206
207
|
"yuv.smart-search.operator.like": "similar",
|
|
207
208
|
"yuv.smart-search.operator.not-empty": "is not empty",
|
|
208
209
|
"yuv.smart-search.operator.select": "Select operator...",
|
|
210
|
+
"yuv.smart-search.type.add-type.tooltip": "Add type",
|
|
209
211
|
"yuv.smart-search.type.confirm": "Confirm types",
|
|
210
212
|
"yuv.smart-search.type.remove": "Remove type",
|
|
211
213
|
"yuv.smart-search.type.remove-draft": "Remove selected type",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuuvis/client-framework",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.24.0",
|
|
4
4
|
"author": "OPTIMAL SYSTEMS GmbH <npm@optimal-systems.de>",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"peerDependencies": {
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
"@angular/common": "^21.2.19",
|
|
9
9
|
"@angular/core": "^21.2.19",
|
|
10
10
|
"angular-gridster2": "^21.0.1",
|
|
11
|
-
"@yuuvis/client-core": "^3.
|
|
12
|
-
"@yuuvis/client-shell-core": "^3.
|
|
13
|
-
"@yuuvis/client-components": "^3.
|
|
11
|
+
"@yuuvis/client-core": "^3.24.0",
|
|
12
|
+
"@yuuvis/client-shell-core": "^3.24.0",
|
|
13
|
+
"@yuuvis/client-components": "^3.24.0",
|
|
14
14
|
"ng-dynamic-component": "^10.8.2",
|
|
15
15
|
"modern-normalize": "^3.0.1"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@angular/material": "^21.2.14",
|
|
19
19
|
"@ngrx/signals": "^21.1.0",
|
|
20
|
-
"@yuuvis/material": "^3.
|
|
20
|
+
"@yuuvis/material": "^3.24.0",
|
|
21
21
|
"@yuuvis/media-viewer": "^4.1.0",
|
|
22
22
|
"angular-split": "^20.0.0",
|
|
23
23
|
"vis-network": "^10.0.2",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _angular_forms from '@angular/forms';
|
|
2
2
|
import { ControlValueAccessor, FormControl, Validator, FormGroup, AbstractControl } from '@angular/forms';
|
|
3
3
|
import * as _angular_core from '@angular/core';
|
|
4
|
-
import { OnInit, OnDestroy, ElementRef, WritableSignal, AfterViewInit } from '@angular/core';
|
|
4
|
+
import { OnInit, OnDestroy, ElementRef, DoCheck, WritableSignal, AfterViewInit } from '@angular/core';
|
|
5
5
|
import { AbstractMatFormField } from '@yuuvis/client-framework/common';
|
|
6
6
|
import { TranslateService, Situation, ObjectFormControl, RangeValue, Operator, LocaleNumberPipe, FileSizePipe, OrganizationSetEntry, DateRange, FilesizeRange, FormattedMailTo } from '@yuuvis/client-core';
|
|
7
7
|
import { MetadataFormFieldContext } from '@yuuvis/client-framework/metadata-form';
|
|
@@ -41,6 +41,37 @@ declare class CatalogComponent extends AbstractMatFormField<string | string[]> i
|
|
|
41
41
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<CatalogComponent, "yuv-catalog", never, { "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "classifications": { "alias": "classifications"; "required": false; "isSignal": true; }; "situation": { "alias": "situation"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Form input for a color value. Renders a hex text input alongside a native color picker
|
|
46
|
+
* swatch; both stay in sync. The value is a hex color string (e.g. `#2A70AC`).
|
|
47
|
+
*
|
|
48
|
+
* Implements `ControlValueAccessor` so it can be used within Angular forms and Material form
|
|
49
|
+
* fields.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* <mat-form-field>
|
|
53
|
+
* <mat-label>Primary color</mat-label>
|
|
54
|
+
* <yuv-color formControlName="primaryColor"></yuv-color>
|
|
55
|
+
* </mat-form-field>
|
|
56
|
+
*/
|
|
57
|
+
declare class ColorComponent extends AbstractMatFormField<string> implements ControlValueAccessor, OnInit, OnDestroy {
|
|
58
|
+
#private;
|
|
59
|
+
/** the color swatch (native `<input type="color">`, always a full 6-digit hex) */
|
|
60
|
+
readonly colorFc: FormControl<string>;
|
|
61
|
+
/** the editable hex text input (source of truth for the value) */
|
|
62
|
+
readonly textFc: FormControl<string | null>;
|
|
63
|
+
ngControl: _angular_forms.NgControl | null;
|
|
64
|
+
propagateChange: (_: string | null) => void;
|
|
65
|
+
writeValue(value: string): void;
|
|
66
|
+
registerOnChange(fn: (value: string | null) => void): void;
|
|
67
|
+
registerOnTouched(): void;
|
|
68
|
+
setDisabledState(isDisabled: boolean): void;
|
|
69
|
+
ngOnInit(): void;
|
|
70
|
+
ngOnDestroy(): void;
|
|
71
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ColorComponent, never>;
|
|
72
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ColorComponent, "yuv-color", never, {}, {}, never, never, true, never>;
|
|
73
|
+
}
|
|
74
|
+
|
|
44
75
|
declare enum DataGridSizeType {
|
|
45
76
|
SMALL = "small",
|
|
46
77
|
MEDIUM = "medium",
|
|
@@ -49,6 +80,99 @@ declare enum DataGridSizeType {
|
|
|
49
80
|
AUTO = "auto"
|
|
50
81
|
}
|
|
51
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Column of a table element as it is provided to the row editing dialog.
|
|
85
|
+
*/
|
|
86
|
+
type TableRowColumn = Record<string, unknown> & {
|
|
87
|
+
name: string;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @ignore
|
|
92
|
+
* Scripting element for one cell of the table row that is being edited. Mirrors the
|
|
93
|
+
* properties form scripts know from the elements of `scope.model`, but applies changes
|
|
94
|
+
* to the controls of the row editing dialog instead of the object form.
|
|
95
|
+
*/
|
|
96
|
+
declare class TableRowScopeElement {
|
|
97
|
+
private readonly element;
|
|
98
|
+
private readonly onChange;
|
|
99
|
+
constructor(element: TableRowColumn, onChange: (name: string, change: TableRowScriptingChange) => void);
|
|
100
|
+
/**
|
|
101
|
+
* Called when the user changed the cell value. Triggers the elements `onchange` callback
|
|
102
|
+
* with the element itself and the rows model (siblings), like form scripts get it for table rows.
|
|
103
|
+
*/
|
|
104
|
+
update(value: unknown, rowModel: TableRowScriptingModel): void;
|
|
105
|
+
set value(value: unknown);
|
|
106
|
+
get value(): unknown;
|
|
107
|
+
set required(required: boolean);
|
|
108
|
+
get required(): boolean;
|
|
109
|
+
set readonly(readonly: boolean);
|
|
110
|
+
get readonly(): boolean;
|
|
111
|
+
set error(error: TableRowScriptingError);
|
|
112
|
+
get error(): TableRowScriptingError;
|
|
113
|
+
set onchange(onchange: TableRowScriptingChangeHandler | null);
|
|
114
|
+
get onchange(): TableRowScriptingChangeHandler | null;
|
|
115
|
+
get name(): string;
|
|
116
|
+
get label(): unknown;
|
|
117
|
+
get description(): unknown;
|
|
118
|
+
get type(): unknown;
|
|
119
|
+
get classifications(): unknown;
|
|
120
|
+
get scale(): unknown;
|
|
121
|
+
get precision(): unknown;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
type TableRowScriptingModel = Record<string, TableRowScopeElement>;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The 'row' object passed as second argument to a table element's `onrowedit` form script callback.
|
|
128
|
+
* @see documentation: Form scripting - The 'row' object
|
|
129
|
+
*/
|
|
130
|
+
interface TableRowScriptingRow {
|
|
131
|
+
index: number;
|
|
132
|
+
persisted: boolean;
|
|
133
|
+
saveEnabled: boolean;
|
|
134
|
+
model: TableRowScriptingModel;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Callback run when the row editing dialog of a table opens.
|
|
139
|
+
* @param table the table element (see `TableRowEditSupport.resolveRowEditTable`)
|
|
140
|
+
* @param row the row being edited
|
|
141
|
+
*/
|
|
142
|
+
type TableRowEditCallback = (table: unknown, row: TableRowScriptingRow) => void;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Optional properties a table form element (the `formElement` input of `yuv-data-grid`) may provide
|
|
146
|
+
* to hook into the row editing dialog, e.g. to support the `onrowedit` form script callback.
|
|
147
|
+
* Hosts that don't need row scripting simply omit them.
|
|
148
|
+
*/
|
|
149
|
+
interface TableRowEditSupport {
|
|
150
|
+
/** called whenever the row editing dialog opens */
|
|
151
|
+
onrowedit?: TableRowEditCallback | null;
|
|
152
|
+
/**
|
|
153
|
+
* Resolves the element passed as first argument to `onrowedit` (e.g. the table element of a
|
|
154
|
+
* form scripting scope). Called when the dialog opens. Defaults to the form element itself.
|
|
155
|
+
*/
|
|
156
|
+
resolveRowEditTable?: () => unknown;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
type TableRowScriptingChangeHandler = (element: TableRowScopeElement, rowModel: TableRowScriptingModel) => any;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Change of a row cell property applied by a form script.
|
|
163
|
+
*/
|
|
164
|
+
interface TableRowScriptingChange {
|
|
165
|
+
name: 'value' | 'required' | 'readonly' | 'error';
|
|
166
|
+
newValue: unknown;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Error a form script may set on a row cell, the same shape as for elements of `scope.model`.
|
|
171
|
+
*/
|
|
172
|
+
type TableRowScriptingError = {
|
|
173
|
+
msg: string;
|
|
174
|
+
} | null;
|
|
175
|
+
|
|
52
176
|
declare class DataGridComponent implements ControlValueAccessor, Validator {
|
|
53
177
|
#private;
|
|
54
178
|
readonly translate: TranslateService;
|
|
@@ -128,7 +252,7 @@ declare class DatetimeRangeComponent extends AbstractMatFormField<RangeValue<Dat
|
|
|
128
252
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DatetimeRangeComponent, "yuv-datetime-range", never, { "withTimeInput": { "alias": "withTime"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "operator": { "alias": "operator"; "required": false; "isSignal": true; }; "situation": { "alias": "situation"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
129
253
|
}
|
|
130
254
|
|
|
131
|
-
declare class DatetimeComponent extends AbstractMatFormField<Date | string | null> implements ControlValueAccessor, OnInit {
|
|
255
|
+
declare class DatetimeComponent extends AbstractMatFormField<Date | string | null> implements ControlValueAccessor, OnInit, DoCheck {
|
|
132
256
|
#private;
|
|
133
257
|
private translate;
|
|
134
258
|
pickerCmp: _angular_core.Signal<DatepickerComponent>;
|
|
@@ -161,6 +285,7 @@ declare class DatetimeComponent extends AbstractMatFormField<Date | string | nul
|
|
|
161
285
|
setDisabledState?(isDisabled: boolean): void;
|
|
162
286
|
onValueChange(e: any): void;
|
|
163
287
|
ngOnInit(): void;
|
|
288
|
+
ngDoCheck(): void;
|
|
164
289
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DatetimeComponent, never>;
|
|
165
290
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DatetimeComponent, "yuv-datetime", never, { "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "onlyFutureDates": { "alias": "onlyFutureDates"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "calendar": { "alias": "calendar"; "required": false; "isSignal": true; }; "withTime": { "alias": "withTime"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
166
291
|
}
|
|
@@ -797,7 +922,13 @@ declare class YuvFormsModule {
|
|
|
797
922
|
|
|
798
923
|
declare class FormUtils {
|
|
799
924
|
static getErrorState(control: AbstractControl): boolean;
|
|
925
|
+
/**
|
|
926
|
+
* Writes the errors of a form element's inner control onto the hosting control without
|
|
927
|
+
* dropping the host's own validation result (e.g. `required` set up by the surrounding form).
|
|
928
|
+
* `host.setErrors(inner.errors)` alone would wipe those whenever the inner control is valid.
|
|
929
|
+
*/
|
|
930
|
+
static mergeInnerErrors(host: AbstractControl, inner: AbstractControl): void;
|
|
800
931
|
}
|
|
801
932
|
|
|
802
|
-
export { CatalogComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, DynamicCatalogComponent, FormUtils, I18nCatalogComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, OrganizationSetComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, ReferenceComponent, StringComponent, YuvFormsModule };
|
|
803
|
-
export type { RangeSelectDateValue, RangeSelectFilesizeValue };
|
|
933
|
+
export { CatalogComponent, ColorComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, DynamicCatalogComponent, FormUtils, I18nCatalogComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, OrganizationSetComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, ReferenceComponent, StringComponent, TableRowScopeElement, YuvFormsModule };
|
|
934
|
+
export type { RangeSelectDateValue, RangeSelectFilesizeValue, TableRowEditCallback, TableRowEditSupport, TableRowScriptingChangeHandler, TableRowScriptingError, TableRowScriptingModel, TableRowScriptingRow };
|
|
@@ -112,8 +112,8 @@ declare class QueryListComponent<T = any> {
|
|
|
112
112
|
*
|
|
113
113
|
* Accepts either a structured `SearchQuery` object (field filters, sort orders, etc.)
|
|
114
114
|
* or a raw CMIS query string. The query is re-executed reactively every time this
|
|
115
|
-
* input changes. Set to `null` or `undefined` to
|
|
116
|
-
*
|
|
115
|
+
* input changes. Set to `null` or `undefined` to stop searching: a request still in
|
|
116
|
+
* flight is cancelled, and the list keeps showing the result it has.
|
|
117
117
|
*/
|
|
118
118
|
query: _angular_core.InputSignal<string | SearchQuery | null | undefined>;
|
|
119
119
|
/**
|
|
@@ -326,8 +326,10 @@ declare class QueryListComponent<T = any> {
|
|
|
326
326
|
/**
|
|
327
327
|
* Indicates whether a search request is currently in flight.
|
|
328
328
|
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
329
|
+
* `true` from the moment a query or page request is dispatched to the search service until
|
|
330
|
+
* the latest request settles (response, error or cancellation). A request superseded by a
|
|
331
|
+
* newer one is cancelled, and `busy` stays `true` across that switch. Derived from the request
|
|
332
|
+
* in flight but still writable: a value set from outside holds until the loading state changes.
|
|
331
333
|
* Bind this to a loading indicator or `BusyOverlayDirective` in the parent template:
|
|
332
334
|
* ```html
|
|
333
335
|
* <yuv-query-list #qList ...>...</yuv-query-list>
|
|
@@ -335,6 +337,7 @@ declare class QueryListComponent<T = any> {
|
|
|
335
337
|
* ```
|
|
336
338
|
*/
|
|
337
339
|
busy: _angular_core.WritableSignal<boolean>;
|
|
340
|
+
private readonly paginator;
|
|
338
341
|
constructor();
|
|
339
342
|
/** Resolves the tracking key for a result item in the `@for` loop. */
|
|
340
343
|
trackItem(item: T, index: number): unknown;
|
|
@@ -451,7 +454,7 @@ declare class QueryListComponent<T = any> {
|
|
|
451
454
|
* appear in the current query (e.g. because the index has not been updated), drop it
|
|
452
455
|
* in temporarily so the user sees it immediately without a full refresh.
|
|
453
456
|
*
|
|
454
|
-
* Drop-in items are cleared automatically
|
|
457
|
+
* Drop-in items are cleared automatically once a page the user navigates to is shown.
|
|
455
458
|
* Call `dropItems([])` to remove them programmatically.
|
|
456
459
|
*
|
|
457
460
|
* @param items Items to prepend. Must be of type `T` (same as query result items).
|
|
@@ -531,8 +534,9 @@ declare class QueryListComponent<T = any> {
|
|
|
531
534
|
/**
|
|
532
535
|
* Re-executes the current query without changing the page or query parameters.
|
|
533
536
|
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
537
|
+
* Re-runs what the list is about to show or is showing: a request still in flight, otherwise
|
|
538
|
+
* the page the user is currently on, or the query from scratch if it has only one page. If that
|
|
539
|
+
* page no longer exists — its objects were deleted — the list moves to the last page there is.
|
|
536
540
|
*
|
|
537
541
|
* Use this to reflect server-side changes (e.g. after a create/delete operation)
|
|
538
542
|
* without navigating away from the current view.
|
|
@@ -551,11 +555,14 @@ declare class QueryListComponent<T = any> {
|
|
|
551
555
|
/**
|
|
552
556
|
* Handles a page-change event emitted by the `mat-paginator`.
|
|
553
557
|
*
|
|
554
|
-
*
|
|
555
|
-
*
|
|
558
|
+
* Loads the page for the zero-based `pageEvent.pageIndex`, like `goToPage()`, and clears the
|
|
559
|
+
* drop-in items once that page is shown. If it fails to load, they stay.
|
|
556
560
|
*
|
|
557
561
|
* Bound to `(page)` on the `mat-paginator` in the template.
|
|
558
562
|
*
|
|
563
|
+
* Ignored while the paginator still shows the previous query's result — a new query is loading or
|
|
564
|
+
* failed to load — since its page numbers mean nothing for the current query.
|
|
565
|
+
*
|
|
559
566
|
* @param pageEvent The pagination event emitted by `MatPaginatorModule`.
|
|
560
567
|
*/
|
|
561
568
|
changePage(pageEvent: PageEvent): void;
|
|
@@ -564,9 +571,10 @@ declare class QueryListComponent<T = any> {
|
|
|
564
571
|
*
|
|
565
572
|
* Sets `busy` to `true` for the duration of the request. On success, updates
|
|
566
573
|
* the pagination state, clears all optimistic overrides (they are page-scoped),
|
|
567
|
-
* and replaces `#items` with the new page's results.
|
|
568
|
-
*
|
|
569
|
-
*
|
|
574
|
+
* and replaces `#items` with the new page's results. A request still in flight — an earlier
|
|
575
|
+
* page change or a new query — is cancelled. If loading the page fails, the list and the
|
|
576
|
+
* paginator stay on the page that was loaded before. A page past the last one loads the last
|
|
577
|
+
* page instead.
|
|
570
578
|
*
|
|
571
579
|
* @param page One-based page number to navigate to.
|
|
572
580
|
*/
|