BrowserNavigator
BrowserNavigator
is a class that implements navigation using the browser's History API. This navigator extends the standard one, providing basic navigation functionality and logic specific to the browser's history.
Constructor
To create an instance of this class, developers can use the class constructor, which accepts history items, a cursor (index) pointing to the entry in the history items list, and additional options:
import { BrowserNavigator } from '@telegram-apps/sdk';
new BrowserNavigator(['/index'], 0);
new BrowserNavigator([{ pathname: '/a' }, { pathname: '/b' }], 1);
WARNING
If an empty history items list or a cursor pointing to a non-existent item is passed, the constructor will throw an appropriate error.
postEvent
The postEvent
function allows replacing a function that calls Mini Apps methods on behalf of the navigator.
const n = new BrowserNavigator(['/'], 0, {
postEvent(method, payload) {
console.log('postEvent:', method, payload);
},
});
hashMode
The hashMode
property allows a developer to set the navigation mode used by the navigator. Allowed values are classic
(#pathname
), slash
(#/pathname
), and null
. Passing the null
value switches the navigator from SPA mode to MPA mode, using the entire href
instead of the hash part of the location.
By default, the navigator uses the classic
mode.
const n = new BrowserNavigator(['/'], 0, {
hashMode: 'slash'
});
base
The base
property is responsible for parsing routes and rendering paths assuming that they must start with the specified base
value.
const n = new BrowserNavigator(['/'], 0, {
hashMode: null,
base: '/solidjs-template',
});
n.renderPath('/home'); // -> /solidjs-template/home
This value is only useful when you are using the MPA mode.
createBrowserNavigatorFromLocation
To simplify the process of creating BrowserNavigator
, the package provides the createBrowserNavigatorFromLocation
method. Depending on the options (which are constructor options described previously) passed, it parses the current location and creates a BrowserNavigator
instance.
import { createBrowserNavigatorFromLocation } from '@telegram-apps/sdk';
const navigator = createBrowserNavigatorFromLocation({
hashMode: 'slash',
});
initNavigator
The initNavigator
function is responsible for creating a BrowserNavigator
instance using previously saved navigator state. It also automatically saves it in the session storage for future state restoration.
This function accepts session storage key name, which will contain navigator's state and an optional object, representing navigator constructor options.
import { initNavigator } from '@telegram-apps/sdk';
const n = initNavigator('app-navigator-state', {
hashMode: 'slash',
});
In case, the function was unable to restore the navigator using the session storage, it will utilize the createBrowserNavigatorFromLocation
function.
Attaching
Creating an instance of BrowserNavigator
and using its methods doesn't automatically update the browser history. To achieve this, developers should attach it. Until then, the navigator will only update its internal state and notify all its subscribers about changes. Manual attachment is necessary to prevent situations where several navigators of this type are created, each trying to control the browser history with its internal state.
To allow the navigator to control the browser's history, it is required to attach it via the attach
method:
import { BrowserNavigator } from '@telegram-apps/sdk';
const navigator = new BrowserNavigator(...);
navigator.attach().then(() => {
console.log('Attachment completed');
});
This method returns a promise that will be resolved when the attachment is completed.
To stop the navigator from modifying the browser's history, use the detach
method:
navigator.detach();
Navigating
The navigator provides a list of methods for developers to manipulate the navigation history.
back
Goes back in history by 1.
navigator.back();
forward
Goes forward in history by 1.
navigator.forward();
go
Changes the currently active history item index by the specified delta. This method doesn't change the index if the updated index points to a non-existing history item. This behavior is preserved until the fit
argument is specified. If it is specified, the method adjusts the passed delta to fit within the bounds [0, history.length - 1]
.
// Goes back in history by 3 entries.
navigator.go(-3);
// Will surely do nothing in real-world applications.
navigator.go(-100000);
// Will go back to the oldest entry.
navigator.go(-100000, true);
// Will go forward to the newest entry.
navigator.go(100000, true);
goTo
Goes to the specified index. The method does nothing if the passed index is out of bounds.
If the fit
option is specified and the index is out of bounds, it will be adjusted to the nearest bound.
// Will do nothing.
navigator.goTo(-1);
// Will go to the oldest entry.
navigator.goTo(0);
// Will surely do nothing in real-world applications.
navigator.goTo(100000);
// Will go back to the oldest entry.
navigator.goTo(-100000, true);
// Will go forward to the newest entry.
navigator.goTo(100000, true);
push
Pushes a new history item. The method replaces all entries after the current one with the one being pushed. Note that the passed item is always relative. If you want to use it as an absolute one, use the /
prefix. Example: /absolute
, { pathname: '/absolute' }
.
To create a final path, the navigator uses a method, used in the URL class constructor, resolving a path based on the current one.
In the upcoming examples, let's assume that the current entry is /home/blog
.
Absolute pathname
Specifying an absolute path will not merge it with the current one; instead, it will be used in its entirety:
navigator.push('/database');
// or
navigator.push({ pathname: '/database' });
// Navigator will add a new entry, and the current one becomes /database
Relative pathname
Specifying a relative pathname will exhibit the same behavior as in the browser:
navigator.push('license');
// or
navigator.push({ pathname: 'license' });
// Navigator will add a new entry, and the current one becomes /home/license
Search
To add an entry with query parameters, use a question mark (?
) or the search
entry property:
navigator.push('?id=1');
// or
navigator.push({ search: '?id=1' });
// Navigator will add a new entry, and the current one becomes /home/blog?id=1
INFO
Pushing a new pathname with different or missing query parameters will result in the loss of current query parameters. To prevent this, the developer should pass them again.
Hash
Adding the hash part of the entry follows the same logic as search, but using a hashtag (#
) and the hash
entry property.
navigator.push('#introduction');
// or
navigator.push({ hash: '#introduction' });
// Navigator will add a new entry, and the current
// one becomes /home/blog#introduction
replace
The replace
method functions similarly to the push method, but it doesn't create a new entry. Instead, it replaces the current one.
Properties
index
Current history cursor.
const navigator = new BrowserNavigator(['/'], 0);
navigator.index; // 0
id
Current history item identifier. The navigator generates them itself if an id is not specified explicitly.
const navigator = new BrowserNavigator(['/'], 0);
navigator.id; // 'abb721'
const navigator2 = new BrowserNavigator([{ id: 'a', pathname: '/' }], 0);
navigator2.id; // 'a'
hash
Current history item hash.
const navigator = new BrowserNavigator(['/#jungle'], 0);
navigator.hash; // "#jungle"
hasPrev
True if the navigator has items before the current item.
const navigator = new BrowserNavigator(['/'], 0);
navigator.hasPrev; // false
const navigator2 = new BrowserNavigator(['/a', '/b'], 1);
navigator2.hasPrev; // true
hasNext
True if the navigator has items after the current item.
const navigator = new BrowserNavigator(['/'], 0);
navigator.hasNext; // false
const navigator2 = new BrowserNavigator(['/a', '/b'], 0);
navigator2.hasNext; // true
history
Safe to modify navigation history.
const navigator = new BrowserNavigator(['/a#a-hash', '/b?b-query=1'], 0);
navigator.history;
// [
// { pathname: '/a', hash: '#a-hash', search: '', id: 'ahJJ123' },
// { pathname: '/b', hash: '', search: '?b-query=1', id: 'dd82' },
// ]
path
Path, including pathname, search, and hash.
const navigator = new BrowserNavigator([{
pathname: '/a',
hash: '#mama',
search: '?joe',
}], 0);
navigator.path; // '/a?joe#mama'
pathname
Current pathname. Always starts with a slash.
const navigator = new BrowserNavigator([{
pathname: '/a',
hash: '#mama',
search: '?joe',
}], 0);
navigator.pathname; // '/a'
search
Current query parameters.
const navigator = new BrowserNavigator([{
pathname: '/a',
hash: '#mama',
search: '?joe',
}], 0);
navigator.search; // '?joe'
state
Current history item state.
const navigator = new BrowserNavigator([{ state: 'test' }], 0);
navigator.state; // 'test'
Events
BrowserNavigator
provides on
and off
methods to manage event listeners. Currently, the only event available for listening is change
. The change
event's payload is an object containing the following properties:
navigator: BrowserNavigator
: The related navigator instance.delta: number
: The delta of the currently active item cursor.from: { pathname: string; hash: string; search: string; id: string; state?: State }
: The previously active history item.to
: An object with the same structure asfrom
, representing the currently active history item.
Adding an Event Listener
To add an event listener for the change
event, use the on
method:
const removeEventListener = navigator.on('change', (ev) => {
console.warn('Navigation state changed', ev);
});
Removing an Event Listener
To remove an event listener, call the function returned by the on
method:
removeEventListener();
Alternatively, you could use the navigator's off
method:
function listener(ev) {
console.warn('Navigation state changed', ev);
}
navigator.on('change', listener);
navigator.off('change', listener);
Other Methods
renderPath
The renderPath
method combines the navigator's base
property with the given path data, applying the navigator's navigation mode. This method returns the fully rendered path as a string.
const n = new BrowserNavigator(['/'], 0, {
hashMode: 'slash',
});
n.renderPath('/test'); // '#/test'
const n2 = new BrowserNavigator(['/'], 0, {
base: '/my-base',
hashMode: 'slash',
});
n2.renderPath('/test'); // '#/my-base/test'
const n3 = new BrowserNavigator(['/'], 0, {
base: '/my-base',
hashMode: null,
});
n3.renderPath('/test'); // '/my-base/test'
parsePath
The parsePath
method parses the provided path according to the current navigation type and returns it as an object. This method helps to understand how the navigator interprets the given path.
const n = new BrowserNavigator(['/'], 0);
n.parsePath('/test');
// { pathname: '/', search: '', hash: '' }
n.parsePath('/test#abc');
// { pathname: '/abc', search: '', hash: '' }
n.parsePath('/test#abc?query#some-hash');
// { pathname: '/abc', search: '?query', hash: '#some-hash' }
const n2 = new BrowserNavigator(['/'], 0, { hashMode: null });
n2.parsePath('/test');
// { pathname: '/test', search: '', hash: '' }
n2.parsePath('/test#abc');
// { pathname: '/test', search: '', hash: '#abc' }
n2.parsePath('/test?query#abc');
// { pathname: '/test', search: '?query', hash: '#abc' }