# @selfage/stateful_navigator

## Install

`npm install @selfage/stateful_navigator`

## Overview

Written in TypeScript and compiled to ES6 with inline source map & source. See [@selfage/tsconfig](https://www.npmjs.com/package/@selfage/tsconfig) for full compiler options. Provides classes to manage associate observable state with browser history.

## Observable state

This library is based on `@selfage/observable` to provide an observable state, which is a data object typically generated by `@selfage/generator_cli`.

Suppose a `STATE` variable is generated and exported in a file `./state.ts`.

## Loader and updater

```TypeScript
import { createLoaderAndUpdater } from '@selfage/stateful_navigator';
import { STATE } from './state';

let queryParamKey = 'q';
let [loader, updater] = createLoaderAndUpdater(STATE, queryParamKey);
// Now build your DOM tree and add listeners on loader.state
// loader.state.on('page', ...)

// When the state is changed and you want a new history entry.
updater.push();
// When the state is changed and you don't want a new histroy entry.
updater.replace();
```

`queryParamKey` is used to compose a query param `q=...` or to read from that query param, which holds a stringified state.

`createLoaderAndUpdater()` adds a listener to `popstate` event to handle users clicking browser's back button, by parsing the query param `q=<stringified historical state>`. However, you have to add listeners to each field of `loader.state` to actually handle the state change.

`updater.push()` should be called whenever you want a new history entry with the current state, which creates a new query param `q=<stringfied current state>` in the URL. It shouldn't be called with every field change, because you may want to group several changes together as one history entry. `updater.replace()` is the same as `updater.push()` except it replace the currrent URL without creating a new history entry.

The type of `loader` is `HistoryLoader<State>` by `import {HistoryLoader} from '@selfage/stateful_navigator/history_loader'` and the type of `updater` is `HistoryUpdater` by `import {HistoryUpdater} '@selfage/stateful_navigator/history_updater'`;
