Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions apps/docs/docs/components/pagination/_both.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<flowbite-pagination
[currentPage]="1"
[totalItems]="100"
[navigation]="'both'" />
[navigationMode]="'both'" />
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[currentPage]="20"
[totalItems]="100000"
[pageSize]="50"
[firstLast]="false"
[hasFirstLast]="false"
[ariaLabel]="'Custom pagination'"
[customStyle]="{
root: { base: 'flex gap-2' },
Expand Down
15 changes: 1 addition & 14 deletions apps/docs/docs/components/pagination/_default.component.html
Original file line number Diff line number Diff line change
@@ -1,14 +1 @@
<table>
@for (item of testDatas().items; track $index) {
<tr>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
}
</table>

<flowbite-pagination
[currentPage]="currentPage()"
(currentPageChange)="pageChangeHandler($event)"
[totalItems]="testDatas().totalItems"
[pageSize]="pageSize()" />
<flowbite-pagination [totalItems]="1000" />
57 changes: 2 additions & 55 deletions apps/docs/docs/components/pagination/_default.component.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,10 @@
import { PaginationComponent } from 'flowbite-angular/pagination';

import { Component, signal } from '@angular/core';
import { Component } from '@angular/core';

@Component({
// ng-doc-ignore-line
selector: 'flowbite-demo-pagination-default',
imports: [PaginationComponent],
// ng-doc-ignore-line
templateUrl: './_default.component.html',
})
export class FlowbiteDefaultComponent {
private readonly _testDatas: IdNameDto[] = [];

readonly currentPage = signal(1);
readonly pageSize = signal(10);
readonly testDatas = signal(PagedResult.empty<IdNameDto>());

constructor() {
// fetch test datas
for (let i = 1; i <= 105; i++) {
this._testDatas.push({ id: i, name: 'John Doe' });
}

// simulate API call
this.pageChangeHandler(1);
}

pageChangeHandler(page: number) {
this.currentPage.set(page);

// Call your API here
// The following lines of code simulates a backend query
const _items: IdNameDto[] = [];
const _start = (this.currentPage() - 1) * this.pageSize();
const _end = Math.min(this._testDatas.length, _start + this.pageSize());

for (let i = _start; i < _end; i++) {
_items.push({ id: i + 1, name: 'John Doe' });
}

this.testDatas.set({
items: _items,
totalItems: this._testDatas.length,
});
}
}

export interface IdNameDto {
id: number;
name: string;
}

export interface PagedResult<T> {
items: T[];
totalItems: number;
}

export const PagedResult = {
empty<T>(): PagedResult<T> {
return { items: [], totalItems: 0 };
},
};
export class FlowbiteDefaultComponent {}
3 changes: 1 addition & 2 deletions apps/docs/docs/components/pagination/_text.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<flowbite-pagination
[currentPage]="1"
[totalItems]="100"
[navigation]="'text'" />
[navigationMode]="'text'" />
8 changes: 5 additions & 3 deletions libs/flowbite-angular/pagination/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
export {
PaginationComponent,
paginationDefaultValueProvider,
FLOWBITE_PAGINATION_CURRENT_PAGE_DEFAULT_VALUE,
FLOWBITE_PAGINATION_BUTTON_PROPERTIES_DEFAULT_VALUE,
FLOWBITE_PAGINATION_CUSTOM_STYLE_DEFAULT_VALUE,
FLOWBITE_PAGINATION_PREVIOUS_ICON_DEFAULT_VALUE,
FLOWBITE_PAGINATION_NEXT_ICON_DEFAULT_VALUE,
FLOWBITE_PAGINATION_FIRST_ICON_DEFAULT_VALUE,
FLOWBITE_PAGINATION_LAST_ICON_DEFAULT_VALUE,
FLOWBITE_PAGINATION_TABS_DEFAULT_VALUE,
FLOWBITE_PAGINATION_PAGE_SIZE_DEFAULT_VALUE,
FLOWBITE_PAGINATION_FIRSTLAST_DEFAULT_VALUE,
FLOWBITE_PAGINATION_PREVNEXT_DEFAULT_VALUE,
FLOWBITE_PAGINATION_NAVIGATION_DEFAULT_VALUE,
FLOWBITE_PAGINATION_HAS_FIRST_LAST_DEFAULT_VALUE,
FLOWBITE_PAGINATION_HAS_PREV_NEXT_DEFAULT_VALUE,
FLOWBITE_PAGINATION_NAVIGATION_MODE_DEFAULT_VALUE,
FLOWBITE_PAGINATION_SIZE_DEFAULT_VALUE,
} from './pagination.component';
export type { PaginationProperties, PaginationClass, PaginationTheme } from './pagination.theme';
Expand Down
84 changes: 45 additions & 39 deletions libs/flowbite-angular/pagination/pagination.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import {
} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

export const FLOWBITE_PAGINATION_CURRENT_PAGE_DEFAULT_VALUE = new InjectionToken<number>(
'FLOWBITE_PAGINATION_CURRENT_PAGE_DEFAULT_VALUE'
);

export const FLOWBITE_PAGINATION_CUSTOM_STYLE_DEFAULT_VALUE = new InjectionToken<
DeepPartial<PaginationTheme>
>('FLOWBITE_PAGINATION_CUSTOM_STYLE_DEFAULT_VALUE');
Expand Down Expand Up @@ -59,17 +63,17 @@ export const FLOWBITE_PAGINATION_PAGE_SIZE_DEFAULT_VALUE = new InjectionToken<nu
'FLOWBITE_PAGINATION_PAGE_SIZE_DEFAULT_VALUE'
);

export const FLOWBITE_PAGINATION_FIRSTLAST_DEFAULT_VALUE = new InjectionToken<boolean>(
'FLOWBITE_PAGINATION_FIRSTLAST_DEFAULT_VALUE'
export const FLOWBITE_PAGINATION_HAS_FIRST_LAST_DEFAULT_VALUE = new InjectionToken<boolean>(
'FLOWBITE_PAGINATION_HAS_FIRST_LAST_DEFAULT_VALUE'
);

export const FLOWBITE_PAGINATION_PREVNEXT_DEFAULT_VALUE = new InjectionToken<boolean>(
'FLOWBITE_PAGINATION_PREVNEXT_DEFAULT_VALUE'
export const FLOWBITE_PAGINATION_HAS_PREV_NEXT_DEFAULT_VALUE = new InjectionToken<boolean>(
'FLOWBITE_PAGINATION_HAS_PREV_NEXT_DEFAULT_VALUE'
);

export const FLOWBITE_PAGINATION_NAVIGATION_DEFAULT_VALUE = new InjectionToken<
export const FLOWBITE_PAGINATION_NAVIGATION_MODE_DEFAULT_VALUE = new InjectionToken<
keyof PaginationNavigation
>('FLOWBITE_PAGINATION_NAVIGATION_DEFAULT_VALUE');
>('FLOWBITE_PAGINATION_NAVIGATION_MODE_DEFAULT_VALUE');

export const FLOWBITE_PAGINATION_SIZE_DEFAULT_VALUE = new InjectionToken<keyof PaginationSizes>(
'FLOWBITE_PAGINATION_SIZE_DEFAULT_VALUE'
Expand All @@ -80,6 +84,10 @@ export const FLOWBITE_PAGINATION_BUTTON_PROPERTIES_DEFAULT_VALUE = new Injection
>('FLOWBITE_PAGINATION_BUTTON_PROPERTIES_DEFAULT_VALUE');

export const paginationDefaultValueProvider = makeEnvironmentProviders([
{
provide: FLOWBITE_PAGINATION_CURRENT_PAGE_DEFAULT_VALUE,
useValue: 1,
},
{
provide: FLOWBITE_PAGINATION_CUSTOM_STYLE_DEFAULT_VALUE,
useValue: {},
Expand Down Expand Up @@ -109,15 +117,15 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
useValue: 25,
},
{
provide: FLOWBITE_PAGINATION_FIRSTLAST_DEFAULT_VALUE,
provide: FLOWBITE_PAGINATION_HAS_FIRST_LAST_DEFAULT_VALUE,
useValue: true,
},
{
provide: FLOWBITE_PAGINATION_PREVNEXT_DEFAULT_VALUE,
provide: FLOWBITE_PAGINATION_HAS_PREV_NEXT_DEFAULT_VALUE,
useValue: true,
},
{
provide: FLOWBITE_PAGINATION_NAVIGATION_DEFAULT_VALUE,
provide: FLOWBITE_PAGINATION_NAVIGATION_MODE_DEFAULT_VALUE,
useValue: 'icon',
},
{
Expand Down Expand Up @@ -150,7 +158,7 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
standalone: true,
imports: [IconComponent, NgTemplateOutlet, ButtonComponent],
template: `
@if (firstLast()) {
@if (hasFirstLast()) {
<flowbite-button
type="button"
data-active="false"
Expand All @@ -159,7 +167,7 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
[fill]="buttonProperties().fill!"
[size]="size()"
[customStyle]="buttonProperties().customStyle!">
@if (['icon', 'both'].includes(navigation())) {
@if (['icon', 'both'].includes(navigationMode())) {
@if (firstIcon()) {
<ng-container [ngTemplateOutlet]="firstIcon()!" />
} @else {
Expand All @@ -168,13 +176,13 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
[class]="contentClasses().iconClass" />
}
}
@if (['text', 'both'].includes(navigation())) {
@if (['text', 'both'].includes(navigationMode())) {
<span>First</span>
}
</flowbite-button>
}

@if (prevNext()) {
@if (hasPrevNext()) {
<flowbite-button
type="button"
data-active="false"
Expand All @@ -183,7 +191,7 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
[fill]="buttonProperties().fill!"
[size]="size()"
[customStyle]="buttonProperties().customStyle!">
@if (['icon', 'both'].includes(navigation())) {
@if (['icon', 'both'].includes(navigationMode())) {
@if (previousIcon()) {
<ng-container [ngTemplateOutlet]="previousIcon()!" />
} @else {
Expand All @@ -192,7 +200,7 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
[class]="contentClasses().iconClass" />
}
}
@if (['text', 'both'].includes(navigation())) {
@if (['text', 'both'].includes(navigationMode())) {
<span>Previous</span>
}
</flowbite-button>
Expand All @@ -202,7 +210,7 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
<flowbite-button
type="button"
[attr.data-active]="page === currentPage()"
(click)="changePage(page)"
(click)="goToPage(page)"
[color]="buttonProperties().color!"
[fill]="buttonProperties().fill!"
[size]="size()"
Expand All @@ -211,7 +219,7 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
</flowbite-button>
}

@if (prevNext()) {
@if (hasPrevNext()) {
<flowbite-button
type="button"
data-active="false"
Expand All @@ -220,10 +228,10 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
[fill]="buttonProperties().fill!"
[size]="size()"
[customStyle]="buttonProperties().customStyle!">
@if (['text', 'both'].includes(navigation())) {
@if (['text', 'both'].includes(navigationMode())) {
<span>Next</span>
}
@if (['icon', 'both'].includes(navigation())) {
@if (['icon', 'both'].includes(navigationMode())) {
@if (lastIcon()) {
<ng-container [ngTemplateOutlet]="lastIcon()!" />
} @else {
Expand All @@ -235,7 +243,7 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
</flowbite-button>
}

@if (firstLast()) {
@if (hasFirstLast()) {
<flowbite-button
type="button"
data-active="false"
Expand All @@ -244,10 +252,10 @@ export const paginationDefaultValueProvider = makeEnvironmentProviders([
[fill]="buttonProperties().fill!"
[size]="size()"
[customStyle]="buttonProperties().customStyle!">
@if (['text', 'both'].includes(navigation())) {
@if (['text', 'both'].includes(navigationMode())) {
<span>Last</span>
}
@if (['icon', 'both'].includes(navigation())) {
@if (['icon', 'both'].includes(navigationMode())) {
@if (lastIcon()) {
<ng-container [ngTemplateOutlet]="lastIcon()!" />
} @else {
Expand Down Expand Up @@ -277,17 +285,17 @@ export class PaginationComponent extends BaseComponent<PaginationClass> {
public readonly domSanitizer = inject(DomSanitizer);

/**
* Value of the current page
* Value of the total items
*
* @required
*/
public readonly currentPage = model.required<number>();
public readonly totalItems = model.required<number>();
/**
* Value of the total items
* Value of the current page
*
* @required
* @default 1
*/
public readonly totalItems = model.required<number>();
public readonly currentPage = model(inject(FLOWBITE_PAGINATION_CURRENT_PAGE_DEFAULT_VALUE));
/**
* Value of how many tabs are displayed
*
Expand All @@ -305,19 +313,19 @@ export class PaginationComponent extends BaseComponent<PaginationClass> {
*
* @default true
*/
public readonly prevNext = model(inject(FLOWBITE_PAGINATION_PREVNEXT_DEFAULT_VALUE));
public readonly hasPrevNext = model(inject(FLOWBITE_PAGINATION_HAS_PREV_NEXT_DEFAULT_VALUE));
/**
* Whether to show or hide first and last buttons
*
* @default true
*/
public readonly firstLast = model(inject(FLOWBITE_PAGINATION_FIRSTLAST_DEFAULT_VALUE));
public readonly hasFirstLast = model(inject(FLOWBITE_PAGINATION_HAS_FIRST_LAST_DEFAULT_VALUE));
/**
* Value of the navigation button's type
*
* @default icon
*/
public readonly navigation = model(inject(FLOWBITE_PAGINATION_NAVIGATION_DEFAULT_VALUE));
public readonly navigationMode = model(inject(FLOWBITE_PAGINATION_NAVIGATION_MODE_DEFAULT_VALUE));
/**
* Value of the component's size
*
Expand Down Expand Up @@ -474,43 +482,41 @@ export class PaginationComponent extends BaseComponent<PaginationClass> {
//#endregion

/**
* Sets the value of the `currentPage`
* Sets the value of the `currentPage` if it's between 1 and `maxPages`
* @param page number of the active page
*/
public changePage(page: number) {
if (this.visibleCurrentPage() === page) return;
public goToPage(page: number) {
if (page < 1 || page > this.maxPages()) return;
this.currentPage.set(page);
}

/**
* Decreases the value of `currentPage` if it's bigger than 1
* Decreases the value of `currentPage` if it's more than 1
*/
public goToPreviousPage() {
if (this.visibleCurrentPage() === 1) return;
if (this.visibleCurrentPage() <= 1) return;
this.currentPage.update((value) => value - 1);
}

/**
* Increases the value of `currentPage` if it's smaller than `maxPages`
* Increases the value of `currentPage` if it's less than `maxPages`
*/
public goToNextPage() {
if (this.visibleCurrentPage() === this.maxPages()) return;
if (this.visibleCurrentPage() >= this.maxPages()) return;
this.currentPage.update((value) => value + 1);
}

/**
* Sets the value of `currentPage` to 1
*/
public goToFirstPage() {
if (this.currentPage() === 1) return;
this.currentPage.set(1);
}

/**
* Sets the value of `currentPage` equal to `maxPages`
*/
public goToLastPage() {
if (this.currentPage() === this.maxPages()) return;
this.currentPage.set(this.maxPages());
}
}
Loading
Loading