diff --git a/packages/devextreme-angular/src/ui/card-view/nested/pager.ts b/packages/devextreme-angular/src/ui/card-view/nested/pager.ts index 9d8adff7d9d1..43522054e6b6 100644 --- a/packages/devextreme-angular/src/ui/card-view/nested/pager.ts +++ b/packages/devextreme-angular/src/ui/card-view/nested/pager.ts @@ -82,10 +82,10 @@ export class DxoCardViewPagerComponent extends NestedOption implements OnDestroy } @Input() - get showPageSizeSelector(): boolean { + get showPageSizeSelector(): boolean | Mode { return this._getOption('showPageSizeSelector'); } - set showPageSizeSelector(value: boolean) { + set showPageSizeSelector(value: boolean | Mode) { this._setOption('showPageSizeSelector', value); } diff --git a/packages/devextreme-angular/src/ui/data-grid/nested/pager.ts b/packages/devextreme-angular/src/ui/data-grid/nested/pager.ts index e5ed41960566..a1f442a87dd3 100644 --- a/packages/devextreme-angular/src/ui/data-grid/nested/pager.ts +++ b/packages/devextreme-angular/src/ui/data-grid/nested/pager.ts @@ -82,10 +82,10 @@ export class DxoDataGridPagerComponent extends NestedOption implements OnDestroy } @Input() - get showPageSizeSelector(): boolean { + get showPageSizeSelector(): boolean | Mode { return this._getOption('showPageSizeSelector'); } - set showPageSizeSelector(value: boolean) { + set showPageSizeSelector(value: boolean | Mode) { this._setOption('showPageSizeSelector', value); } diff --git a/packages/devextreme-angular/src/ui/nested/base/pager.ts b/packages/devextreme-angular/src/ui/nested/base/pager.ts index 974018feb34c..f791fe4b0473 100644 --- a/packages/devextreme-angular/src/ui/nested/base/pager.ts +++ b/packages/devextreme-angular/src/ui/nested/base/pager.ts @@ -54,10 +54,10 @@ export abstract class DxoPager extends NestedOption { this._setOption('showNavigationButtons', value); } - get showPageSizeSelector(): boolean { + get showPageSizeSelector(): Mode | boolean { return this._getOption('showPageSizeSelector'); } - set showPageSizeSelector(value: boolean) { + set showPageSizeSelector(value: Mode | boolean) { this._setOption('showPageSizeSelector', value); } diff --git a/packages/devextreme-angular/src/ui/pagination/index.ts b/packages/devextreme-angular/src/ui/pagination/index.ts index 1910b8ba6fdf..20c3238a8af0 100644 --- a/packages/devextreme-angular/src/ui/pagination/index.ts +++ b/packages/devextreme-angular/src/ui/pagination/index.ts @@ -20,7 +20,7 @@ import { } from '@angular/core'; -import { DisplayMode } from 'devextreme/common'; +import { DisplayMode, Mode } from 'devextreme/common'; import { EventInfo } from 'devextreme/common/core/events'; import DxPagination from 'devextreme/ui/pagination'; @@ -300,10 +300,10 @@ export class DxPaginationComponent extends DxComponent implements OnDestroy, OnC */ @Input() - get showPageSizeSelector(): boolean { + get showPageSizeSelector(): boolean | Mode { return this._getOption('showPageSizeSelector'); } - set showPageSizeSelector(value: boolean) { + set showPageSizeSelector(value: boolean | Mode) { this._setOption('showPageSizeSelector', value); } @@ -509,7 +509,7 @@ export class DxPaginationComponent extends DxComponent implements OnDestroy, OnC * This member supports the internal infrastructure and is not intended to be used directly from your code. */ - @Output() showPageSizeSelectorChange: EventEmitter; + @Output() showPageSizeSelectorChange: EventEmitter; /** diff --git a/packages/devextreme-angular/src/ui/tree-list/nested/pager.ts b/packages/devextreme-angular/src/ui/tree-list/nested/pager.ts index d60835e078df..f7ee23072a3d 100644 --- a/packages/devextreme-angular/src/ui/tree-list/nested/pager.ts +++ b/packages/devextreme-angular/src/ui/tree-list/nested/pager.ts @@ -82,10 +82,10 @@ export class DxoTreeListPagerComponent extends NestedOption implements OnDestroy } @Input() - get showPageSizeSelector(): boolean { + get showPageSizeSelector(): boolean | Mode { return this._getOption('showPageSizeSelector'); } - set showPageSizeSelector(value: boolean) { + set showPageSizeSelector(value: boolean | Mode) { this._setOption('showPageSizeSelector', value); } diff --git a/packages/devextreme-react/src/card-view.ts b/packages/devextreme-react/src/card-view.ts index 3f9f937fde89..fd4e843cd6fb 100644 --- a/packages/devextreme-react/src/card-view.ts +++ b/packages/devextreme-react/src/card-view.ts @@ -1951,7 +1951,7 @@ type IPagerProps = React.PropsWithChildren<{ label?: string; showInfo?: boolean; showNavigationButtons?: boolean; - showPageSizeSelector?: boolean; + showPageSizeSelector?: boolean | Mode; visible?: boolean | Mode; }> const _componentPager = (props: IPagerProps) => { diff --git a/packages/devextreme-react/src/data-grid.ts b/packages/devextreme-react/src/data-grid.ts index 2ccce8b026e3..20314e721c57 100644 --- a/packages/devextreme-react/src/data-grid.ts +++ b/packages/devextreme-react/src/data-grid.ts @@ -2150,7 +2150,7 @@ type IPagerProps = React.PropsWithChildren<{ label?: string; showInfo?: boolean; showNavigationButtons?: boolean; - showPageSizeSelector?: boolean; + showPageSizeSelector?: boolean | Mode; visible?: boolean | Mode; }> const _componentPager = (props: IPagerProps) => { diff --git a/packages/devextreme-react/src/tree-list.ts b/packages/devextreme-react/src/tree-list.ts index 77ee94fa5ca6..7225e37ecf8e 100644 --- a/packages/devextreme-react/src/tree-list.ts +++ b/packages/devextreme-react/src/tree-list.ts @@ -1826,7 +1826,7 @@ type IPagerProps = React.PropsWithChildren<{ label?: string; showInfo?: boolean; showNavigationButtons?: boolean; - showPageSizeSelector?: boolean; + showPageSizeSelector?: boolean | Mode; visible?: boolean | Mode; }> const _componentPager = (props: IPagerProps) => { diff --git a/packages/devextreme-vue/src/card-view.ts b/packages/devextreme-vue/src/card-view.ts index 30519845ca11..655fe0324c11 100644 --- a/packages/devextreme-vue/src/card-view.ts +++ b/packages/devextreme-vue/src/card-view.ts @@ -2372,7 +2372,7 @@ const DxPagerConfig = { label: String, showInfo: Boolean, showNavigationButtons: Boolean, - showPageSizeSelector: Boolean, + showPageSizeSelector: [Boolean, String] as PropType, visible: [Boolean, String] as PropType } }; diff --git a/packages/devextreme-vue/src/data-grid.ts b/packages/devextreme-vue/src/data-grid.ts index b08e1adbaaa3..2670c86e10bb 100644 --- a/packages/devextreme-vue/src/data-grid.ts +++ b/packages/devextreme-vue/src/data-grid.ts @@ -2694,7 +2694,7 @@ const DxPagerConfig = { label: String, showInfo: Boolean, showNavigationButtons: Boolean, - showPageSizeSelector: Boolean, + showPageSizeSelector: [Boolean, String] as PropType, visible: [Boolean, String] as PropType } }; diff --git a/packages/devextreme-vue/src/pagination.ts b/packages/devextreme-vue/src/pagination.ts index 697f02d94995..845d5125e42a 100644 --- a/packages/devextreme-vue/src/pagination.ts +++ b/packages/devextreme-vue/src/pagination.ts @@ -5,6 +5,7 @@ import Pagination, { Properties } from "devextreme/ui/pagination"; import DOMComponent from "devextreme/core/dom_component"; import { DisplayMode, + Mode, } from "devextreme/common"; import { EventInfo, @@ -70,7 +71,7 @@ const componentConfig = { rtlEnabled: Boolean, showInfo: Boolean, showNavigationButtons: Boolean, - showPageSizeSelector: Boolean, + showPageSizeSelector: [Boolean, String] as PropType, tabIndex: Number, visible: Boolean, width: [Number, String] diff --git a/packages/devextreme-vue/src/tree-list.ts b/packages/devextreme-vue/src/tree-list.ts index 05fa72d4b82f..cbd79ef4a48b 100644 --- a/packages/devextreme-vue/src/tree-list.ts +++ b/packages/devextreme-vue/src/tree-list.ts @@ -2377,7 +2377,7 @@ const DxPagerConfig = { label: String, showInfo: Boolean, showNavigationButtons: Boolean, - showPageSizeSelector: Boolean, + showPageSizeSelector: [Boolean, String] as PropType, visible: [Boolean, String] as PropType } }; diff --git a/packages/devextreme/js/__internal/pagination/__tests__/content.test.ts b/packages/devextreme/js/__internal/pagination/__tests__/content.test.ts new file mode 100644 index 000000000000..f4750bfe3722 --- /dev/null +++ b/packages/devextreme/js/__internal/pagination/__tests__/content.test.ts @@ -0,0 +1,124 @@ +import { describe, expect, it } from '@jest/globals'; +import type { ComponentWrapperProps } from '@ts/core/r1/component_wrapper'; + +import Pagination from '../wrappers/pagination'; + +describe('Pagination: pagination visibility', () => { + const createPagination = (config: ComponentWrapperProps): { + container: HTMLElement; + pagination: Pagination; + } => { + const container = document.createElement('div'); + const pagination = new Pagination(container, { + pageSize: 10, + pageIndex: 1, + pagesNavigatorVisible: 'auto', + hasKnownLastPage: true, + showInfo: false, + showNavigationButtons: false, + showPageSizeSelector: false, + ...config, + }); + return { container, pagination }; + }; + + const isPagesContainerVisible = (container: HTMLElement): boolean => { + const pagesContainer = container.querySelector('.dx-pages'); + expect(pagesContainer).toBeTruthy(); + const style = pagesContainer?.getAttribute('style'); + const isVisible = style === null || !style?.includes('visibility: hidden'); + return isVisible; + }; + + const isPagesContainerHidden = (container: HTMLElement): boolean => { + const pagesContainer = container.querySelector('.dx-pages'); + expect(pagesContainer).toBeTruthy(); + const isHidden = pagesContainer?.getAttribute('style')?.includes('visibility: hidden') ?? false; + return isHidden; + }; + + describe('when pageCount = 1', () => { + it('should hide container when no explicit visible components are enabled', () => { + const { container } = createPagination({ itemCount: 5, pageSize: 10 }); + + expect(isPagesContainerHidden(container)).toBe(true); + }); + + it('should hide container when showPageSizeSelector is set to auto', () => { + const { container } = createPagination({ itemCount: 5, pageSize: 10, showPageSizeSelector: 'auto' }); + + expect(isPagesContainerHidden(container)).toBe(true); + }); + + it('should show container when showInfo is enabled', () => { + const { container } = createPagination({ + itemCount: 8, + pageSize: 10, + showInfo: true, + }); + + expect(isPagesContainerVisible(container)).toBe(true); + }); + + it('should show container when showNavigationButtons is enabled', () => { + const { container } = createPagination({ + itemCount: 6, + pageSize: 10, + showNavigationButtons: true, + }); + + expect(isPagesContainerVisible(container)).toBe(true); + }); + + it('should show container when showPageSizeSelector is enabled', () => { + const { container } = createPagination({ + itemCount: 9, + pageSize: 10, + showPageSizeSelector: true, + allowedPageSizes: [5, 10, 'all'], + }); + + expect(isPagesContainerVisible(container)).toBe(true); + }); + }); + + describe('when pageCount > 1', () => { + it('should always show container regardless of other settings', () => { + const { container } = createPagination({ + itemCount: 25, + pageSize: 10, + }); + + expect(isPagesContainerVisible(container)).toBe(true); + }); + }); + + describe('dynamic visibility changes', () => { + it('should toggle visibility when showInfo changes at runtime', () => { + const { container, pagination } = createPagination({ + itemCount: 7, + pageSize: 10, + }); + + pagination.option('showInfo', true); + + expect(isPagesContainerVisible(container)).toBe(true); + + pagination.option('showInfo', false); + + expect(isPagesContainerHidden(container)).toBe(true); + }); + }); + + it('should keep info block visible when pageSize > itemCount and showInfo=true (T1299780)', () => { + const { container } = createPagination({ + itemCount: 4, + pageSize: 10, + showInfo: true, + allowedPageSizes: [4, 6, 11], + }); + + const infoBlock = container.querySelector('.dx-info'); + expect(infoBlock).toBeTruthy(); + }); +}); diff --git a/packages/devextreme/js/__internal/pagination/common/base_pagination_props.ts b/packages/devextreme/js/__internal/pagination/common/base_pagination_props.ts index bddc0fa54a79..de8a747198fe 100644 --- a/packages/devextreme/js/__internal/pagination/common/base_pagination_props.ts +++ b/packages/devextreme/js/__internal/pagination/common/base_pagination_props.ts @@ -18,7 +18,7 @@ export interface BasePaginationProps extends BaseWidgetProps { visible?: boolean; hasKnownLastPage?: boolean; pagesNavigatorVisible?: boolean | 'auto'; - showPageSizeSelector?: boolean; + showPageSizeSelector?: boolean | 'auto'; allowedPageSizes: (number | PageSize)[]; rtlEnabled?: boolean; showNavigationButtons?: boolean; @@ -37,7 +37,7 @@ export const BasePaginationDefaultProps: BasePaginationProps = { visible: true, hasKnownLastPage: true, pagesNavigatorVisible: 'auto', - showPageSizeSelector: true, + showPageSizeSelector: 'auto', allowedPageSizes: [5, 10], showNavigationButtons: false, itemCount: 1, diff --git a/packages/devextreme/js/__internal/pagination/content.tsx b/packages/devextreme/js/__internal/pagination/content.tsx index d92a18e94384..881882e6a791 100644 --- a/packages/devextreme/js/__internal/pagination/content.tsx +++ b/packages/devextreme/js/__internal/pagination/content.tsx @@ -159,10 +159,24 @@ export class PaginationContent extends InfernoComponent } getPagesContainerVisibility(): 'hidden' | undefined { - if (this.props.pagesNavigatorVisible === 'auto' && this.props.pageCount === 1 && this.props.hasKnownLastPage) { - return 'hidden'; - } - return undefined; + const { + pagesNavigatorVisible, + pageCount, + hasKnownLastPage, + showInfo, + showNavigationButtons, + showPageSizeSelector, + } = this.props; + + const shouldHideBasedOnPageCount = pagesNavigatorVisible === 'auto' && pageCount === 1 && hasKnownLastPage; + + const hasExplicitVisibleComponents = Boolean(showInfo) || Boolean(showNavigationButtons) + || showPageSizeSelector === true; + + const shouldHide = shouldHideBasedOnPageCount && !hasExplicitVisibleComponents; + const result = shouldHide ? 'hidden' : undefined; + + return result; } getIsLargeDisplayMode(): boolean { diff --git a/packages/devextreme/js/ui/pagination.d.ts b/packages/devextreme/js/ui/pagination.d.ts index 20b0c1bf1256..903f365106cb 100644 --- a/packages/devextreme/js/ui/pagination.d.ts +++ b/packages/devextreme/js/ui/pagination.d.ts @@ -1,6 +1,7 @@ import Widget, { WidgetOptions } from './widget/ui.widget'; import { DisplayMode, + Mode, } from '../common'; export { @@ -40,9 +41,9 @@ export type PagerBase = { /** * @docid * @public - * @default false + * @default "auto" */ - showPageSizeSelector?: boolean; + showPageSizeSelector?: boolean | Mode; /** * @docid * @public diff --git a/packages/devextreme/ts/dx.all.d.ts b/packages/devextreme/ts/dx.all.d.ts index 37808f0f796a..2d2d346e0ebd 100644 --- a/packages/devextreme/ts/dx.all.d.ts +++ b/packages/devextreme/ts/dx.all.d.ts @@ -1447,7 +1447,7 @@ declare module DevExpress.common { /** * [descr:PagerBase.showPageSizeSelector] */ - showPageSizeSelector?: boolean; + showPageSizeSelector?: boolean | Mode; /** * [descr:PagerBase.label] */