# URL state

> Build shareable table links for pagination, sorting, filters, and search.

Source: https://docs.inertiax.dev/table/guide/url-state/

Name the table with a stable, unique component ID. `OrdersTable::make('orders')` uses the five query keys below; the URL prefix comes from this ID, not a database table or React page name.

## Query keys

| Key               | Value                           |
| ----------------- | ------------------------------- |
| `orders_page`     | One-based page, such as `2`     |
| `orders_per_page` | Allowed page size, such as `25` |
| `orders_sort`     | JSON list of sort objects       |
| `orders_filters`  | JSON filter group               |
| `orders_search`   | Search string                   |

```text
/orders?orders_page=2&orders_per_page=25&orders_search=acme
```

Pagination must be enabled, 25 must be an allowed size, and the table must have a searchable column. Selection and column visibility are not persisted in these query keys.

## Sort links

Decoded sort value:

```json
[{"direction":"desc","key":"reference"}]
```

Encoded URL:

```text
/orders?orders_sort=%5B%7B%22direction%22%3A%22desc%22%2C%22key%22%3A%22reference%22%7D%5D
```

Use `key` and `direction` (`asc` or `desc`) for new links. Laravel also accepts the compatibility object `{"id":"reference","desc":true}`. The frontend writes the `key`/`direction` shape; `initialSort('-reference')` is PHP shorthand, not the URL representation.

## Filter links

Decoded filter value:

```json
{"conditions":[{"clause":"equals","key":"status","value":"paid"}],"operator":"and"}
```

Encoded URL:

```text
/orders?orders_filters=%7B%22conditions%22%3A%5B%7B%22clause%22%3A%22equals%22%2C%22key%22%3A%22status%22%2C%22value%22%3A%22paid%22%7D%5D%2C%22operator%22%3A%22and%22%7D
```

The table must declare a `status` filter with an `equals` clause. Include `paid` in its options to offer that value in the picker. Groups use `operator` and `conditions`; conditions use `key`, `clause`, and `value`, which is `null` for a clause that takes no value, such as `is-not-set`. See [Filter groups](https://docs.inertiax.dev/table/reference/filter/#filter-groups) for nested groups and compatibility input forms.

Encode JSON once as a query value. With `URLSearchParams`, pass the JSON string directly; pre-encoding it with `encodeURIComponent()` would encode the percent signs again.

## Defaults and browser history

When you open a page without table query parameters, table interactions omit values matching its initial state: page 1, the configured page size, initial sorting, filters, and search. Returning a value to that state removes a key added by interactions. Omission means “use the default”, not “disable this feature”.

Keys explicitly present when you opened the page may remain, even when their values match that initial state. InertiaX retains them because the server may already have applied the URL input; removing them could change the next response. Other tables’ keys and unrelated parameters are preserved.

For example, start at `/orders` with empty search, search for `acme`, then open page 2. Changing the search to `globex` replaces:

```text
/orders?orders_search=acme&orders_page=2
/orders?orders_search=globex
```

The standard Inertia component replaces the current browser history entry. Back returns to the previous navigation rather than each keystroke. See [Browser history](https://docs.inertiax.dev/table/guide/inertia/#browser-history).

## Stale and invalid links

Invalid URL input shows a problem inside the affected table, with an explicit [reset action](https://docs.inertiax.dev/table/guide/url-recovery/). The page and other tables remain available. Standalone serialization, explicitly provided PHP state, and invalid custom-source results remain strict.
