diff --git a/NEWS.md b/NEWS.md
index 0357e0b2..ecac8e10 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,12 @@
# reactable 0.4.4.9000 (Unreleased)
+## New features
+
+* New [`Reactable.gotoPage()`](https://glin.github.io/reactable/articles/javascript-api.html#reactable-gotopage)
+ and [`Reactable.setPageSize()`](https://glin.github.io/reactable/articles/javascript-api.html#reactable-setpagesize)
+ methods in the JavaScript API to change the current page or set the current page size.
+ ([#322](https://github.com/glin/reactable/issues/322))
+
# reactable 0.4.4
[Documentation - reactable 0.4.4](https://v0-4-4--reactable-docs.netlify.app/)
diff --git a/srcjs/Reactable.js b/srcjs/Reactable.js
index 27b23200..4c8768ea 100644
--- a/srcjs/Reactable.js
+++ b/srcjs/Reactable.js
@@ -114,6 +114,14 @@ export function onStateChange(tableId, listenerFn) {
return getInstance(tableId).onStateChange(listenerFn)
}
+export function gotoPage(tableId, pageIndex) {
+ getInstance(tableId).gotoPage(pageIndex)
+}
+
+export function setPageSize(tableId, pageSize) {
+ getInstance(tableId).setPageSize(pageSize)
+}
+
export default function Reactable({
data,
columns,
diff --git a/srcjs/__tests__/Reactable.test.js b/srcjs/__tests__/Reactable.test.js
index eca0c4c4..45c3e926 100644
--- a/srcjs/__tests__/Reactable.test.js
+++ b/srcjs/__tests__/Reactable.test.js
@@ -21,6 +21,19 @@ afterEach(() => jest.clearAllMocks())
expect.extend(matchers)
+// expect.toThrow() doesn't suppress console errors, so this can be used to test errors instead.
+// https://github.com/jestjs/jest/issues/5785
+const expectToThrow = func => {
+ // Even though the error is caught, it still gets printed to the console
+ // so we mock that out to avoid the wall of red text.
+ jest.spyOn(console, 'error')
+ console.error.mockImplementation(() => {})
+
+ expect(func).toThrow()
+
+ console.error.mockRestore()
+}
+
const getRoot = container => container.querySelector('.Reactable.ReactTable')
const getTable = container => container.querySelector('.rt-table')
const getThead = container => container.querySelector('.rt-thead')
@@ -9819,8 +9832,12 @@ describe('reactable JavaScript API', () => {
expect(queryByText('col-a')).toBeVisible()
expect(queryByText('col-c')).toBeVisible()
- act(() => reactable.setHiddenColumns('my-tbl', prevHiddenColumns => prevHiddenColumns.concat('b')))
- act(() => reactable.setHiddenColumns('my-tbl', prevHiddenColumns => prevHiddenColumns.concat('c')))
+ act(() =>
+ reactable.setHiddenColumns('my-tbl', prevHiddenColumns => prevHiddenColumns.concat('b'))
+ )
+ act(() =>
+ reactable.setHiddenColumns('my-tbl', prevHiddenColumns => prevHiddenColumns.concat('c'))
+ )
expect(reactable.getState('my-tbl').hiddenColumns).toEqual(['b', 'c'])
expect(queryByText('col-b')).toEqual(null)
expect(queryByText('col-c')).toEqual(null)
@@ -9936,4 +9953,64 @@ describe('reactable JavaScript API', () => {
await waitFor(() => expect(currentState.searchValue).toEqual('aaa'))
await waitFor(() => expect(currentState.groupBy).toEqual(['a']))
})
+
+ it('Reactable.gotoPage', () => {
+ const props = {
+ data: { a: ['a1', 'a2', 'a3', 'a4', 'a5', 'a6'] },
+ columns: [{ name: 'a', id: 'a' }],
+ defaultPageSize: 2,
+ elementId: 'my-tbl'
+ }
+ const { queryByText } = render()
+
+ expect(reactable.getState('my-tbl').pageIndex).toEqual(0)
+
+ act(() => reactable.gotoPage('my-tbl', 1))
+ expect(reactable.getState('my-tbl').pageIndex).toEqual(1)
+ expect(queryByText('a1')).toEqual(null)
+ expect(queryByText('a3')).toBeVisible()
+
+ act(() => reactable.gotoPage('my-tbl', 0))
+ expect(reactable.getState('my-tbl').pageIndex).toEqual(0)
+ expect(queryByText('a1')).toBeVisible()
+ expect(queryByText('a3')).toEqual(null)
+
+ // Should ignore page indexes beyond range
+ act(() => reactable.gotoPage('my-tbl', 1))
+ act(() => reactable.gotoPage('my-tbl', -1))
+ expect(reactable.getState('my-tbl').pageIndex).toEqual(1)
+ act(() => reactable.gotoPage('my-tbl', 999))
+ expect(reactable.getState('my-tbl').pageIndex).toEqual(1)
+
+ // Should accept a callback
+ act(() => reactable.gotoPage('my-tbl', currentIndex => currentIndex + 1))
+ expect(reactable.getState('my-tbl').pageIndex).toEqual(2)
+ act(() => reactable.gotoPage('my-tbl', currentIndex => currentIndex - 1))
+ expect(reactable.getState('my-tbl').pageIndex).toEqual(1)
+ })
+})
+
+it('Reactable.setPageSize', () => {
+ const props = {
+ data: { a: ['a1', 'a2', 'a3', 'a4', 'a5', 'a6'] },
+ columns: [{ name: 'a', id: 'a' }],
+ defaultPageSize: 2,
+ elementId: 'my-tbl'
+ }
+ const { queryByText } = render()
+
+ expect(reactable.getState('my-tbl').pageSize).toEqual(2)
+
+ act(() => reactable.setPageSize('my-tbl', 1))
+ expect(reactable.getState('my-tbl').pageSize).toEqual(1)
+ expect(queryByText('a2')).toEqual(null)
+
+ act(() => reactable.setPageSize('my-tbl', 6))
+ expect(reactable.getState('my-tbl').pageSize).toEqual(6)
+
+ act(() => reactable.setPageSize('my-tbl', 999))
+ expect(reactable.getState('my-tbl').pageSize).toEqual(999)
+
+ // Invalid values should err
+ expectToThrow(() => act(() => reactable.setPageSize('my-tbl', -1)))
})
diff --git a/vignettes/javascript-api.Rmd b/vignettes/javascript-api.Rmd
index 4ebe6b11..bb8709c8 100644
--- a/vignettes/javascript-api.Rmd
+++ b/vignettes/javascript-api.Rmd
@@ -675,6 +675,64 @@ server <- function(input, output) {
shinyApp(ui, server)
```
+### `Reactable.gotoPage()`
+
+::: {.callout}
+New in v0.4.4.9000
+:::
+
+Changes the current page. `pageIndex` can either be a number or a function that takes
+the previous `pageIndex` and returns the new value.
+
+`pageIndex` is zero-based, so the first page would have a `pageIndex` of `0`.
+If `pageIndex` is outside the valid `pageIndex` range, `Reactable.gotoPage()` will do nothing.
+
+```ts
+Reactable.gotoPage(
+ tableId: string,
+ pageIndex?: number | Function
+)
+```
+
+#### Examples
+
+```js
+// Go to page index 0 (the first page)
+Reactable.gotoPage('cars-table', 0)
+
+// Go to page index 2 (the third page)
+Reactable.gotoPage('cars-table', 2)
+
+// Go to the next page
+Reactable.gotoPage('cars-table', prevPage => prevPage + 1)
+
+// Go to the previous page
+Reactable.gotoPage('cars-table', prevPage => prevPage - 1)
+```
+
+### `Reactable.setPageSize()`
+
+::: {.callout}
+New in v0.4.4.9000
+:::
+
+Sets the current page size.
+
+```ts
+Reactable.gotoPage(
+ tableId: string,
+ pageSize?: number
+)
+```
+
+#### Examples
+
+```js
+// Set the page size to 10
+Reactable.setPageSize('cars-table', 10)
+```
+
+
```{css echo=FALSE}
/* rmarkdown html documents */
.main-container {