@open-rlb/ng-bootstrap 3.3.24 → 3.3.26

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.
@@ -0,0 +1,364 @@
1
+ ---
2
+ name: rlb-components
3
+ description: Expert guidance for the @open-rlb/ng-bootstrap Angular component library (buttons, cards, dropdowns, toasts, loaders, badges, progress, etc.), built on Angular signals, OnPush, and Bootstrap 5. Use when using or composing these UI components.
4
+ ---
5
+
6
+ # RLB ng-Bootstrap Components Skill
7
+
8
+ You are an expert in the **@open-rlb/ng-bootstrap** Angular component library. All components use Angular 18+ signals, `ChangeDetectionStrategy.OnPush`, and Bootstrap 5. Import via `RlbBootstrapModule` or individual standalone imports.
9
+
10
+ ## Shared Types
11
+
12
+ ```typescript
13
+ type Color = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark';
14
+ type Size = 'sm' | 'md' | 'lg';
15
+ type TextAlignment = 'left' | 'center' | 'right';
16
+ ```
17
+
18
+ ---
19
+
20
+ ## Buttons
21
+
22
+ ```html
23
+ <!-- Basic button -->
24
+ <button rlb-button color="primary" size="md">Click me</button>
25
+ <button rlb-button color="danger" outline>Delete</button>
26
+ <button rlb-button color="secondary" [disabled]="true">Disabled</button>
27
+ <a rlb-button color="info" isLink>Link</a>
28
+
29
+ <!-- Button group -->
30
+ <rlb-button-group orientation="horizontal" size="md">
31
+ <button rlb-button color="primary">A</button>
32
+ <button rlb-button color="primary">B</button>
33
+ </rlb-button-group>
34
+
35
+ <!-- FAB (Floating Action Button) -->
36
+ <rlb-fab color="primary" size="md" position="br">
37
+ <i class="bi bi-plus"></i>
38
+ </rlb-fab>
39
+ ```
40
+
41
+ **Button inputs:** `color`, `size`, `disabled`, `outline`, `isLink`
42
+ **FAB inputs:** `color`, `size`, `disabled`, `outline`, `position` ('br'|'bl'|'tr'|'tl')
43
+
44
+ ---
45
+
46
+ ## Alerts
47
+
48
+ ```html
49
+ <rlb-alert color="success">Operation successful.</rlb-alert>
50
+ <rlb-alert color="danger" [dismissible]="true" (dismissed)="onDismiss()">
51
+ An error occurred!
52
+ </rlb-alert>
53
+ ```
54
+
55
+ **Inputs:** `color`, `dismissible` (boolean), `class`
56
+ **Outputs:** `dismissed`
57
+
58
+ ---
59
+
60
+ ## Badges
61
+
62
+ ```html
63
+ <span rlb-badge color="primary">New</span>
64
+ <span rlb-badge color="success" [pill]="true">Active</span>
65
+ <span rlb-badge color="danger" [border]="true">3</span>
66
+ ```
67
+
68
+ **Inputs:** `color`, `pill`, `border`, `hidden-text`, `class`, `badge-text-color`
69
+
70
+ ---
71
+
72
+ ## Avatar
73
+
74
+ ```html
75
+ <rlb-avatar [size]="48" shape="circle" src="/assets/user.png"></rlb-avatar>
76
+ <rlb-avatar [size]="40" shape="round">AB</rlb-avatar>
77
+ <rlb-avatar [size]="56" shape="square" src="/assets/logo.png"></rlb-avatar>
78
+ ```
79
+
80
+ **Inputs:** `size` (px number), `shape` ('circle'|'round'|'square'), `src`, `class`
81
+
82
+ ---
83
+
84
+ ## Cards
85
+
86
+ ```html
87
+ <rlb-card align="left" background="light">
88
+ <rlb-card-header>Card Title</rlb-card-header>
89
+ <rlb-card-image src="/img.png"></rlb-card-image>
90
+ <rlb-card-body>
91
+ <rlb-card-title>Title</rlb-card-title>
92
+ <rlb-card-subtitle>Subtitle</rlb-card-subtitle>
93
+ <rlb-card-text>Body text here.</rlb-card-text>
94
+ <rlb-card-link href="/more">Read more</rlb-card-link>
95
+ </rlb-card-body>
96
+ <rlb-card-footer>Footer</rlb-card-footer>
97
+ </rlb-card>
98
+ ```
99
+
100
+ **Card inputs:** `align`, `overlay`, `background` (Color), `border` (Color)
101
+ **Sub-components:** `rlb-card-body`, `rlb-card-header`, `rlb-card-footer`, `rlb-card-image`, `rlb-card-title`, `rlb-card-subtitle`, `rlb-card-text`, `rlb-card-link`
102
+
103
+ ---
104
+
105
+ ## Accordion
106
+
107
+ ```html
108
+ <rlb-accordion [flush]="false" [always-open]="false" [card-style]="true">
109
+ <rlb-accordion-item>
110
+ <ng-template rlb-accordion-header>Section 1</ng-template>
111
+ <ng-template rlb-accordion-body>Content 1</ng-template>
112
+ </rlb-accordion-item>
113
+ <rlb-accordion-item>
114
+ <ng-template rlb-accordion-header>Section 2</ng-template>
115
+ <ng-template rlb-accordion-body>Content 2</ng-template>
116
+ </rlb-accordion-item>
117
+ </rlb-accordion>
118
+ ```
119
+
120
+ **Inputs:** `flush`, `always-open`, `card-style`, `id`
121
+
122
+ ---
123
+
124
+ ## Tabs
125
+
126
+ ```html
127
+ <rlb-tabs view="tab" [vertical]="false" fill="fill">
128
+ <rlb-tab title="Tab 1">Content for tab 1</rlb-tab>
129
+ <rlb-tab title="Tab 2">Content for tab 2</rlb-tab>
130
+ <rlb-tab title="Tab 3" [disabled]="true">Disabled</rlb-tab>
131
+ </rlb-tabs>
132
+ ```
133
+
134
+ **Inputs:** `view` ('tab'|'pills'|'underline'|'none'), `vertical`, `fill` ('fill'|'justified'), `horizontal-alignment` ('center'|'end'), `id`, `class`
135
+
136
+ ---
137
+
138
+ ## Carousel
139
+
140
+ ```html
141
+ <rlb-carousel
142
+ autoplay="auto"
143
+ [interval]="3000"
144
+ pause="hover"
145
+ [wrap]="true"
146
+ [hide-indicators]="false"
147
+ [hide-controls]="false"
148
+ [(current-slide)]="currentSlide"
149
+ (slid)="onSlid($event)"
150
+ >
151
+ <rlb-carousel-slide active>
152
+ Slide 1
153
+ <rlb-carousel-caption>
154
+ <h5>First slide</h5>
155
+ </rlb-carousel-caption>
156
+ </rlb-carousel-slide>
157
+ <rlb-carousel-slide>Slide 2</rlb-carousel-slide>
158
+ </rlb-carousel>
159
+ ```
160
+
161
+ **Children:** `rlb-carousel-slide` (input `active`, `id`), `rlb-carousel-caption`
162
+ **Inputs:** `autoplay` (`'auto' | 'manual' | 'none'`), `interval`, `pause`, `wrap`, `cross-fade`, `hide-indicators`, `hide-controls`, `no-touch`, `keyboard`, `id`
163
+ **Two-way:** `current-slide`
164
+ **Outputs:** `slid`, `slide`, `slide-count`
165
+ **Methods (via viewChild):** `prev()`, `next()`, `to(index)`, `pause()`, `cycle()`
166
+
167
+ ### Wizard pattern (multi-step form)
168
+
169
+ There is no separate wizard component — a wizard **is** a carousel used as a controlled stepper.
170
+ Disable autoplay/controls/indicators/touch, drive `current-slide` from your own Back / Next buttons,
171
+ and gate `Next` on the current step's validity. Often embedded in a modal (see the `rlb-modals` skill).
172
+
173
+ ```html
174
+ <div [formGroup]="form">
175
+ <rlb-carousel
176
+ autoplay="none"
177
+ no-touch
178
+ hide-controls
179
+ hide-indicators
180
+ [current-slide]="page()"
181
+ (current-slideChange)="page.set($event)"
182
+ (slide-count)="count.set($event)"
183
+ id="wizard"
184
+ >
185
+ <rlb-carousel-slide active>
186
+ <div formGroupName="account"><!-- step 1 fields --></div>
187
+ </rlb-carousel-slide>
188
+ <rlb-carousel-slide>
189
+ <div formGroupName="profile"><!-- step 2 fields --></div>
190
+ </rlb-carousel-slide>
191
+ </rlb-carousel>
192
+ </div>
193
+
194
+ <button rlb-button outline [disabled]="page() === 0" (click)="prev()">Back</button>
195
+ @if (page() < count() - 1) {
196
+ <button rlb-button color="primary" [disabled]="currentStepInvalid()" (click)="next()">Next</button>
197
+ } @else {
198
+ <button rlb-button color="success" [disabled]="form.invalid" (click)="onFinish()">Finish</button>
199
+ }
200
+ ```
201
+
202
+ ```typescript
203
+ readonly page = signal(0); // bound one-way to [current-slide]
204
+ readonly count = signal(0); // set from (slide-count)
205
+ readonly groupNames = ['account', 'profile'];
206
+
207
+ // Validate one step at a time to gate the Next button.
208
+ currentStepInvalid(): boolean {
209
+ return !!this.form.get(this.groupNames[this.page()])?.invalid;
210
+ }
211
+ prev() { this.page.update(p => Math.max(0, p - 1)); }
212
+ next() { this.page.update(p => Math.min(this.count() - 1, p + 1)); }
213
+ ```
214
+
215
+ > Key points: bind `[current-slide]` **one-way** and update the signal yourself (don't use `[(...)]`
216
+ > two-way when you drive navigation manually); use `(slide-count)` to detect the last step; keep each
217
+ > step in its own nested `FormGroup` so `currentStepInvalid()` can validate steps independently.
218
+
219
+ ---
220
+
221
+ ## Breadcrumb
222
+
223
+ ```html
224
+ <rlb-breadcrumb
225
+ divider="/"
226
+ [items]="[
227
+ { id: '1', label: 'Home', link: '/' },
228
+ { id: '2', label: 'Products', link: '/products' },
229
+ { id: '3', label: 'Detail' }
230
+ ]"
231
+ />
232
+ ```
233
+
234
+ **Inputs:** `divider`, `items: BreadcrumbItem[]`, `cssClasses`
235
+ **BreadcrumbItem:** `{ id: string; label: string; link?: string }`
236
+
237
+ ---
238
+
239
+ ## Dropdown
240
+
241
+ ```html
242
+ <rlb-dropdown direction="down">
243
+ <button rlb-button color="primary" rlb-dropdown>Actions</button>
244
+ <div rlb-dropdown-menu>
245
+ <a class="dropdown-item" href="#">Option 1</a>
246
+ <a class="dropdown-item" href="#">Option 2</a>
247
+ </div>
248
+ </rlb-dropdown>
249
+ ```
250
+
251
+ **Inputs:** `direction` ('up'|'down'|'left'|'right'|'up-center'|'down-center')
252
+
253
+ ---
254
+
255
+ ## Pagination
256
+
257
+ ```html
258
+ <rlb-pagination size="md" alignment="center">
259
+ <rlb-pagination-item [active]="true">1</rlb-pagination-item>
260
+ <rlb-pagination-item>2</rlb-pagination-item>
261
+ </rlb-pagination>
262
+ ```
263
+
264
+ **Inputs:** `size`, `alignment` ('start'|'center'|'end'), `class`
265
+
266
+ ---
267
+
268
+ ## Navigation (Navbar + Sidebar)
269
+
270
+ ```html
271
+ <rlb-navbar color="primary" [dark]="true" expand="lg" placement="fixed-top">
272
+ <a rlb-navbar-brand href="/">MyApp</a>
273
+ <rlb-navbar-items>
274
+ <a class="nav-link" routerLink="/home">Home</a>
275
+ </rlb-navbar-items>
276
+ </rlb-navbar>
277
+
278
+ <rlb-sidebar [dark]="true" [rounded]="false">
279
+ <rlb-sidebar-item routerLink="/dashboard">Dashboard</rlb-sidebar-item>
280
+ <rlb-sidebar-item routerLink="/settings">Settings</rlb-sidebar-item>
281
+ </rlb-sidebar>
282
+ ```
283
+
284
+ **Navbar inputs:** `dark`, `color`, `placement`, `expand`, `show-sidebar-toggler`, `enable-dropdown-toggler`, `class`
285
+ **Sidebar inputs:** `dark`, `rounded`
286
+
287
+ ---
288
+
289
+ ## Loaders
290
+
291
+ ```html
292
+ <!-- Spinner -->
293
+ <rlb-spinner style="border" color="primary" size="md"></rlb-spinner>
294
+ <rlb-spinner style="grow" color="success" size="sm"></rlb-spinner>
295
+
296
+ <!-- Progress bar -->
297
+ <rlb-progress
298
+ [value]="65"
299
+ [max]="100"
300
+ color="primary"
301
+ [striped]="true"
302
+ [animated]="true"
303
+ [showValue]="true"
304
+ ></rlb-progress>
305
+
306
+ <!-- Infinite progress -->
307
+ <rlb-progress [infinite]="true" color="info"></rlb-progress>
308
+ ```
309
+
310
+ **Spinner inputs:** `style` ('border'|'grow'), `color`, `size`
311
+ **Progress inputs:** `value`, `max`, `min`, `height`, `animated`, `striped`, `infinite`, `showValue`, `color`, `text-color`, `aria-label`
312
+
313
+ ---
314
+
315
+ ## Toast
316
+
317
+ ```typescript
318
+ // In component
319
+ constructor(private toast: ToastService) {}
320
+
321
+ showSuccess() {
322
+ this.toast.openToast('my-toast', 'success-toast').subscribe();
323
+ }
324
+ ```
325
+
326
+ ---
327
+
328
+ ## Tooltip
329
+
330
+ ```html
331
+ <button rlb-button rlb-tooltip title="Helpful tip" placement="top">Hover me</button>
332
+ ```
333
+
334
+ ---
335
+
336
+ ## Collapse & Offcanvas
337
+
338
+ ```html
339
+ <!-- Collapse -->
340
+ <button rlb-button rlb-collapse-toggle target="myCollapse">Toggle</button>
341
+ <rlb-collapse id="myCollapse">Hidden content</rlb-collapse>
342
+
343
+ <!-- Offcanvas -->
344
+ <button rlb-button rlb-offcanvas-toggle target="myPanel">Open Panel</button>
345
+ <rlb-offcanvas id="myPanel" placement="start">Panel content</rlb-offcanvas>
346
+ ```
347
+
348
+ ---
349
+
350
+ ## Module Import
351
+
352
+ ```typescript
353
+ import { RlbBootstrapModule } from '@open-rlb/ng-bootstrap';
354
+
355
+ @NgModule({
356
+ imports: [RlbBootstrapModule]
357
+ })
358
+ export class AppModule {}
359
+ ```
360
+
361
+ Or import individual components for standalone:
362
+ ```typescript
363
+ import { ButtonComponent, AlertComponent, CardComponent } from '@open-rlb/ng-bootstrap';
364
+ ```
@@ -0,0 +1,295 @@
1
+ ---
2
+ name: rlb-datatable
3
+ description: Expert guidance for the @open-rlb/ng-bootstrap rlb-dt-table datatable: pagination (pages or load-more), sorting, filtering, row actions, loading and empty states. Use when building or configuring data tables.
4
+ ---
5
+
6
+ # RLB ng-Bootstrap DataTable Skill
7
+
8
+ You are an expert in the **@open-rlb/ng-bootstrap** datatable component (`rlb-dt-table`). It supports pagination (pages or load-more), sorting, filtering, row actions, loading states, and empty states.
9
+
10
+ ## Component Tree
11
+
12
+ ```
13
+ rlb-dt-table
14
+ ├── rlb-dt-header — column header (sortable/filterable)
15
+ ├── rlb-dt-row — data row (repeated with *ngFor)
16
+ │ ├── rlb-dt-cell — data cell
17
+ │ └── rlb-dt-actions — row action menu
18
+ │ └── rlb-dt-action — individual action item
19
+ ├── rlb-dt-loading — custom loading template
20
+ └── rlb-dt-noitems — custom empty state template
21
+ ```
22
+
23
+ ---
24
+
25
+ ## rlb-dt-table Inputs
26
+
27
+ | Input | Type | Default | Description |
28
+ |-------|------|---------|-------------|
29
+ | `title` | `string` | — | Table title |
30
+ | `items` | `any[]` | `[]` | Data rows |
31
+ | `loading` | `boolean` | `false` | Loading overlay |
32
+ | `card-style` | `boolean` | `true` | Wrap in card |
33
+ | `table-hover` | `boolean` | `false` | Hover highlight |
34
+ | `table-striped` | `boolean` | `false` | Alternating row colors |
35
+ | `table-striped-columns` | `boolean` | `false` | Alternating column colors |
36
+ | `table-bordered` | `boolean` | `false` | Cell borders |
37
+ | `table-borderless` | `boolean` | `false` | Remove all borders |
38
+ | `table-small` | `boolean` | `false` | Compact rows |
39
+ | `pagination-mode` | `'none'\|'load-more'\|'pages'` | `'none'` | Pagination strategy |
40
+ | `total-items` | `number` | — | Total record count |
41
+ | `current-page` | `number` | — | Current page (1-based) |
42
+ | `page-size` | `number` | — | Rows per page |
43
+ | `show-refresh` | `boolean` | `false` | Show refresh button |
44
+ | `show-actions` | `'row'\|'head'` | `'row'` | Actions column position |
45
+ | `creation-strategy` | `'none'\|'modal'\|'page'` | `'none'` | Create button behavior |
46
+ | `creation-url` | `any[]\|string\|null` | — | Router link for 'page' strategy |
47
+ | `load-more-label` | `string` | `'Load more'` | Load more button text |
48
+
49
+ ## rlb-dt-table Outputs
50
+
51
+ | Output | Type | Description |
52
+ |--------|------|-------------|
53
+ | `create-item` | `void` | Fired when create button clicked |
54
+ | `refresh-item` | `void` | Fired when refresh button clicked |
55
+ | `load-more` | `void` | Fired when load-more clicked |
56
+ | `current-pageChange` | `number` | Two-way page binding |
57
+ | `page-sizeChange` | `number` | Two-way page-size binding |
58
+ | `pagination` | `{ page: number; size: number }` | Combined pagination event |
59
+
60
+ ---
61
+
62
+ ## rlb-dt-header Inputs
63
+
64
+ | Input | Type | Default | Description |
65
+ |-------|------|---------|-------------|
66
+ | `field` | `string` | — | Data field name (for sort/filter) |
67
+ | `sortable` | `boolean` | `false` | Enable column sorting |
68
+ | `filtrable` | `boolean` | `false` | Enable column filtering |
69
+ | `type` | `'number'\|'string'` | — | Column data type |
70
+ | `class` | `string` | — | CSS classes |
71
+ | `style` | `string` | — | Inline styles |
72
+
73
+ ## rlb-dt-row Outputs
74
+
75
+ | Output | Type | Description |
76
+ |--------|------|-------------|
77
+ | `row-click` | `MouseEvent` | Row click event |
78
+
79
+ ## rlb-dt-actions Inputs
80
+
81
+ | Input | Type | Default | Description |
82
+ |-------|------|---------|-------------|
83
+ | `disabled` | `boolean` | `false` | Disable all actions |
84
+
85
+ ## rlb-dt-action Inputs
86
+
87
+ | Input | Type | Default | Description |
88
+ |-------|------|---------|-------------|
89
+ | `label` | `string` | — | Action label (required) |
90
+ | `disabled` | `boolean` | `false` | Disable this action |
91
+
92
+ ---
93
+
94
+ ## Basic Table (no pagination)
95
+
96
+ ```html
97
+ <rlb-dt-table
98
+ title="Users"
99
+ [items]="users"
100
+ [loading]="loading"
101
+ [table-hover]="true"
102
+ [table-striped]="true"
103
+ [show-refresh]="true"
104
+ (refresh-item)="loadUsers()"
105
+ >
106
+ <rlb-dt-header field="name" [sortable]="true">Name</rlb-dt-header>
107
+ <rlb-dt-header field="email">Email</rlb-dt-header>
108
+ <rlb-dt-header field="role">Role</rlb-dt-header>
109
+
110
+ <rlb-dt-row *ngFor="let user of users" (row-click)="onRowClick(user)">
111
+ <rlb-dt-cell>{{ user.name }}</rlb-dt-cell>
112
+ <rlb-dt-cell>{{ user.email }}</rlb-dt-cell>
113
+ <rlb-dt-cell>
114
+ <span rlb-badge [color]="user.role === 'admin' ? 'danger' : 'primary'">{{ user.role }}</span>
115
+ </rlb-dt-cell>
116
+ <rlb-dt-actions>
117
+ <rlb-dt-action label="Edit" (click)="editUser(user)"></rlb-dt-action>
118
+ <rlb-dt-action label="Delete" (click)="deleteUser(user)" [disabled]="user.role === 'admin'"></rlb-dt-action>
119
+ </rlb-dt-actions>
120
+ </rlb-dt-row>
121
+
122
+ <rlb-dt-noitems>
123
+ <p class="text-muted text-center py-4">No users found.</p>
124
+ </rlb-dt-noitems>
125
+ </rlb-dt-table>
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Server-side Pagination (pages)
131
+
132
+ ```html
133
+ <rlb-dt-table
134
+ title="Orders"
135
+ [items]="orders"
136
+ [loading]="loading"
137
+ pagination-mode="pages"
138
+ [total-items]="totalOrders"
139
+ [(current-page)]="currentPage"
140
+ [(page-size)]="pageSize"
141
+ (pagination)="onPaginate($event)"
142
+ creation-strategy="modal"
143
+ (create-item)="openCreateModal()"
144
+ >
145
+ <rlb-dt-header field="id" type="number">#</rlb-dt-header>
146
+ <rlb-dt-header field="customer" [sortable]="true">Customer</rlb-dt-header>
147
+ <rlb-dt-header field="amount" type="number" [sortable]="true">Amount</rlb-dt-header>
148
+ <rlb-dt-header field="status">Status</rlb-dt-header>
149
+
150
+ <rlb-dt-row *ngFor="let order of orders">
151
+ <rlb-dt-cell>{{ order.id }}</rlb-dt-cell>
152
+ <rlb-dt-cell>{{ order.customer }}</rlb-dt-cell>
153
+ <rlb-dt-cell>{{ order.amount | currency:'EUR' }}</rlb-dt-cell>
154
+ <rlb-dt-cell>
155
+ <span rlb-badge [color]="statusColor(order.status)">{{ order.status }}</span>
156
+ </rlb-dt-cell>
157
+ <rlb-dt-actions>
158
+ <rlb-dt-action label="View" (click)="viewOrder(order)"></rlb-dt-action>
159
+ <rlb-dt-action label="Cancel" (click)="cancelOrder(order)" [disabled]="order.status !== 'pending'"></rlb-dt-action>
160
+ </rlb-dt-actions>
161
+ </rlb-dt-row>
162
+ </rlb-dt-table>
163
+ ```
164
+
165
+ ```typescript
166
+ @Component({ ... })
167
+ export class OrderListComponent {
168
+ orders: Order[] = [];
169
+ totalOrders = 0;
170
+ currentPage = 1;
171
+ pageSize = 10;
172
+ loading = false;
173
+
174
+ ngOnInit() { this.loadOrders(); }
175
+
176
+ onPaginate({ page, size }: { page: number; size: number }) {
177
+ this.currentPage = page;
178
+ this.pageSize = size;
179
+ this.loadOrders();
180
+ }
181
+
182
+ private loadOrders() {
183
+ this.loading = true;
184
+ this.orderService.getPage(this.currentPage, this.pageSize).subscribe(res => {
185
+ this.orders = res.items;
186
+ this.totalOrders = res.total;
187
+ this.loading = false;
188
+ });
189
+ }
190
+
191
+ statusColor(status: string): Color {
192
+ const map: Record<string, Color> = {
193
+ pending: 'warning',
194
+ confirmed: 'primary',
195
+ shipped: 'info',
196
+ delivered: 'success',
197
+ cancelled: 'danger'
198
+ };
199
+ return map[status] ?? 'secondary';
200
+ }
201
+ }
202
+ ```
203
+
204
+ ---
205
+
206
+ ## Load-more Pattern (infinite scroll style)
207
+
208
+ ```html
209
+ <rlb-dt-table
210
+ [items]="items"
211
+ [loading]="loading"
212
+ pagination-mode="load-more"
213
+ [total-items]="total"
214
+ load-more-label="Load more items"
215
+ (load-more)="loadMore()"
216
+ >
217
+ <rlb-dt-header>Name</rlb-dt-header>
218
+ <rlb-dt-row *ngFor="let item of items">
219
+ <rlb-dt-cell>{{ item.name }}</rlb-dt-cell>
220
+ </rlb-dt-row>
221
+ </rlb-dt-table>
222
+ ```
223
+
224
+ ```typescript
225
+ page = 1;
226
+ items: any[] = [];
227
+ total = 0;
228
+
229
+ loadMore() {
230
+ this.page++;
231
+ this.service.getPage(this.page).subscribe(res => {
232
+ this.items = [...this.items, ...res.items]; // append, don't replace
233
+ this.total = res.total;
234
+ });
235
+ }
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Custom Loading State
241
+
242
+ ```html
243
+ <rlb-dt-table [items]="items" [loading]="loading">
244
+ <!-- headers and rows... -->
245
+
246
+ <rlb-dt-loading>
247
+ <div class="d-flex justify-content-center p-4">
248
+ <rlb-spinner color="primary" size="lg"></rlb-spinner>
249
+ </div>
250
+ </rlb-dt-loading>
251
+ </rlb-dt-table>
252
+ ```
253
+
254
+ ---
255
+
256
+ ## Creation Strategies
257
+
258
+ ```html
259
+ <!-- Modal: fires (create-item) output -->
260
+ <rlb-dt-table creation-strategy="modal" (create-item)="openCreateModal()">...</rlb-dt-table>
261
+
262
+ <!-- Page: navigates to route -->
263
+ <rlb-dt-table creation-strategy="page" creation-url="/users/new">...</rlb-dt-table>
264
+ <rlb-dt-table creation-strategy="page" [creation-url]="['/users', 'new']">...</rlb-dt-table>
265
+
266
+ <!-- None (default): no create button -->
267
+ <rlb-dt-table creation-strategy="none">...</rlb-dt-table>
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Table Style Combinations
273
+
274
+ ```html
275
+ <!-- Compact bordered table -->
276
+ <rlb-dt-table [table-small]="true" [table-bordered]="true" [card-style]="false">
277
+
278
+ <!-- Striped hover table (most common for lists) -->
279
+ <rlb-dt-table [table-striped]="true" [table-hover]="true">
280
+
281
+ <!-- Borderless minimal table -->
282
+ <rlb-dt-table [table-borderless]="true" [card-style]="false">
283
+ ```
284
+
285
+ ---
286
+
287
+ ## Best Practices
288
+
289
+ 1. Always provide `[total-items]` when using `pagination-mode="pages"` — the paginator needs total count.
290
+ 2. Use `[(current-page)]` and `[(page-size)]` for two-way binding; or listen to `(pagination)` for both at once.
291
+ 3. Reset `currentPage = 1` whenever filters/sort change, then reload.
292
+ 4. For append-style lists use `load-more` mode and concat arrays: `this.items = [...this.items, ...newItems]`.
293
+ 5. Provide `<rlb-dt-noitems>` with a helpful message — empty tables are confusing without context.
294
+ 6. Use `[disabled]` on `rlb-dt-action` for conditional actions (e.g., only admins can delete).
295
+ 7. Avoid putting complex logic inside `*ngFor` templates — compute display values in the component.