Работа со Store

В раскладке страницы прикладные элементы не объединены в общий прикладной контрол и могут возникнуть задачи обеспечить взаимосвязь контролов из разных областей.

Например, необходимо обработать нажатие на элементы тулбара и в обработчике повлиять на состояние контрола, который находится в workspace. Типовым примером является кнопка тулбара "Изменить вид отображения списка" в шапке страницы, по клику на которую нужно изменить значение опции у списка, который находится в основной рабочей области.

Для решения подобных задач был разработан Store. Это синглтон, в который можно поместить данные, необходимые для использования контролов, не имеющих общего родителя.

Для каждой страницы в Store создается отдельная область видимости и вы не сможете получить данные или обработать команду с другой страницы.

Store реализован по следующему интерфейсу:

interface IStore {
    get<T>: (propertyName: string) => T;
    dispatch: (propertyName: string, data: unknown) => void;
    sendCommand: (commandName: string) => void;
    onPropertyChanged: (propertyName: string, callback: (data: unknown) => void) => string;
    declareCommand: (commandName: string, callback: (data: unknown) => void) => string;
    unsubscribe: (id: string) => void;
}
  • get — получить значение поля
  • dispatch — изменить значение поля
  • sendCommand — послать команду
  • onPropertyChanged — подписаться на изменение поля
  • declareCommand — подписаться на команду
  • unsubscribe — удалить ссылки на подписку или команду

Примеры использования

  1. Поместить значение:
import Store from 'Controls/Store';_onCheckedChenged(viewMode: string) {
    Store.dispatch('viewMode', viewMode);
}
  1. Получить значение:
import Store from 'Controls/Store';
…
_viewMode: string;
_beforeMount() {
    this._viewMode = Store.get<string>('viewMode');
}
  1. Подписаться на изменение значения:
import Store from 'Controls/Store';
…
_callbackId: number;
_viewMode: string;
_afterMount() {
    this._callbackId = Store.onPropertyChanged('viewMode', (value: string) => {
        this._viewMode = value;
    });
}
_beforeUnmount() {
    Store.unsubscribe(this._callbackId)
}
  1. Послать команду:
import Store from 'Controls/Store';_onPrintClick(viewMode: string) {
    Store.sendCommand('startPrint');
}
  1. Подписаться на команду:
import Store from 'Controls/Store';
…
_callbackId: number;
_afterMount() {
    this._callbackId = Store.declareCommand('startPrint', () => {
        this._children.printer.execute();
    });
}
_beforeUnmount() {
    Store.unsubscribe(this._callbackId)
}

Примеры решения типовых задач

Примеры работы с фильтрацией

Если на вашей странице кнопка фильтров находится в шапке страницы, значит фильтрация у вас работает через Store. При таком режиме работы фильтрации в Store хранятся 2 поля: filterSource и filter.

  • filterSource — это source, установленный в кнопке фильтров.
  • filter — это объект фильтрации, который установлен в списке. Подробнее про filter можно прочитать тут.

Прикладной программист может получать и устанавливать свои значения в эти поля с помощью Store. Кнопка фильтров и список будут реагировать на эти изменения.

Пример изменения текущего значения фильтра:

import Store from 'Controls/Store';
 
_onSomeEvent(event: Event, newFilterData: object): void {
    const currentFilter = Store.get('filter');
    const newFilter = {...currentFilter, ...newFilterData};
    Store.dispatch('filter', newFilter);
}

Также для работы с кнопкой фильтров есть 2 команды:

  • openFilterDetailPanel — при вызове команды будет вызван метод openDetailPanel у кнопки фильтров.
  • resetFilter — при вызове команды будет вызван метод reset у кнопки фильтров.

Если на вашей странице строка поиска находится в шапке страницы, значит поиск у вас работает через Store. При таком режиме работы поиска в Store хранится поле searchValue.

  • searchValue — строковое значение, по которому осуществляется поиск.

Прикладной программист может получить и установить своё значение в это поле с помощью Store. Строка поиска и список будут реагировать на эти изменения.

Пример изменения текущего значения строки поиска:

import Store from 'Controls/Store';
 
_onSomeEvent(event: Event, additionalSearchValue: string): void {
    const currentSearchValue = Store.get('searchValue');
    const newSearchValu = currentSearchValue + ' ' + additionalSearchValue;
    Store.dispatch('searchValue', newSearchValu);
}

Также для работы со строкой поиска добавлена команда:

  • resetSearch — при вызове команды поиск будет очищен.
import Store from 'Controls/Store';_onCustomReset() {
    Store.sendCommand('resetSearch');
}

Примеры обработки команд в тулбаре

При работе с тулбаром возникающие прикладные задачи можно разделить на 2 вида:

  1. Необходимо вызвать метод контрола, который находится в другой области. Например, по клику на кнопку тулбара "Переместить" в шапке страницы нужно вызвать метод у экшена перемещения, который находится в основной рабочей области.
  2. Необходимо изменить состояние, от которого зависят контролы из разных областей. Например, по клику на кнопку тулбара "Изменить вид отображения списка" в шапке страницы нужно изменить значение опции у списка, который находится в основной рабочей области.

Рассмотрим подробнее, как решить эти задачи с помощью Store.

Первый вид задач решается с помощью команд.

В обработчике клика посылается команда:

import Store from 'Controls/Store';_onPrintClick(viewMode: string) {
    Store.sendCommand('startPrint');
}

А в месте, где команду необходимо обработать, делается подписка на команду:

import Store from 'Controls/Store';
…
_callbackId: number;
_afterMount() {
    this._callbackId = Store.declareCommand('startPrint', () => {
        this._children.printer.execute();
    });
}
_beforeUnmount() {
    Store.unsubscribe(this._callbackId)
}

Второй вид задач решается с помощью изменения состояния в Store.

В обработчике клика устанавливается состояние:

import Store from 'Controls/Store';export const toolbarItemClickHandler = () => {
    const viewMode = Store.get<string>('viewMode');
    Store.dispatch('viewMode', viewMode === 'tile' ? 'list' : 'tile');
}

А в месте, где команду необходимо получить измененное состояние, делается подписка:

import Store from 'Controls/Store';
…
_callbackId: number;
_viewMode: string;
_afterMount() {
    this._callbackId = Store.onPropertyChanged('viewMode', (value: string) => {
        this._viewMode = value;
    });
}
_beforeUnmount() {
    Store.unsubscribe(this._callbackId)
}