Фильтрация и поиск

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

Однако в отдельных случаях разработчику приходится решать нешаблонные задачи, работая со специфическими макетами. В общем случае взаимное расположение фильтров, поиска и списка может быть любым, например, таким:

или таким:

В документе рассмотрен принцип разработки реестра со списком, строкой поиска, кнопкой фильтра и быстрым фильтром.

Он поможет разработчику понять, как в контексте задачи нестандартной раскладки оптимально, избегая дублирования кода, организовать поиск и фильтрацию.

Список контролов для организации поиска и фильтрации в реестре

Визуальные контролы

Для реестра используем:

Контролы-контроллеры

Для организации фильтрации в реестре используем контрол-контроллер Controls/filter:Controller.

Возможности:

  • Связывает список с кнопкой фильтров и быстрым фильтром.
  • Передает через контекст настройки фильтрации контролам:
    • filterButtonSource и historyId для Controls/filter:ViewContainer;
    • fastFilterSource для Controls/filter:FastContainer.
  • Принимает изменения от Controls/filter:ViewContainer и Controls/filter:FastContainer передает их списку Controls/list:Container.
  • Если в контрол помещен Controls/list:DataContainer, параметры фильтрации настраиваем на Controls/filter:Controller — он передаст их в Controls/list:DataContainer.

Для организации поиска в реестре используем контрол-контроллер Controls/search:Controller.

Возможности:

  • Связывает список со строкой поиска.
  • Принимает изменения от Controls/search:InputContainer передает их списку Controls/list:Container.

Поиск конфигурируется с помощью опций searchParam, searchDelay и minSearchLength.

Контроллер Controls/search:Controller должен быть обернут в контрол-контейнер Controls/list:DataContainer.

Контролы-контейнеры

Для работы с данными используем Controls/list:DataContainer — загружает данные и передает их через контекст дочерним контролам. Данные конфигурируются с помощью следующих опций контрола:

  • source — источник данных,
  • keyProperty — уникальный идентификатор (ключевое поле) записи списка,
  • navigation — параметры навигации в списке,
  • sorting — параметры сортировки,
  • filter — параметры фильтрации.

Для работы с визуальными контролами реестра используем следующие контролы-контейнеры:

Подсветка при поиске

При поиске, внутри прикладного шаблона элемента списка, searchValue появится в шаблоне, на itemData.

Если используется список с колонками, searchValue так же будет доступен на колонке. При указании displayProperty для каждой колонки будет передаваться needSearchHighlight — флаг, определяющий, нужна ли подсветка.

Для подсветки используется декоратор Controls/decorator:Highlight.

<!-- WML -->
<ws:if data="{{ itemData.searchValue }}"> <!-- searchValue достаточно проверять на наличие -->
    <Controls.decorator:Highlight
        value="{{ itemData.item.description || '' }}"
        highlightedValue="{{ itemData.searchValue || '' }}"
        />
</ws:if>

Настройка поиска со сменой раскладки

Для реализации поиска со сменой раскладки используют функцию TranslitListCall.

Пример разработки реестра с поиском и фильтрацией

Схематически иерархическая структура создаваемого реестра будет выглядеть следующим образом:

Примечание:

Контролы нужно добавлять в контролы-контроллеры (контролы-контейнеры) с помощью опции content.

  1. Создадим раскладку, в которой разместим контролы-представления Controls/search:Input, Controls/filter:View и Controls/list:View. Добавляя в раскладку списочный контрол, не забываем про базовый шаблон.
    <!-- WML -->
    <Controls.search:Input bind:value="_searchValueWithFilters" placeholder="Укажите ФИО, подразделение..."/>
     
    <Controls.filter:View templateName="Controls-demo/FilterSearch/Panel"/>
     
    <Controls.list:View emptyTemplate="Не найдено">
        <ws:itemTemplate>
            <ws:partial template="Controls/list:ItemTemplate">
                <ws:contentTemplate>
                    <div class="demo-FilterSearch__listItem-wrapper">
                        <span class="demo-FilterSearch__department">{{itemTemplate.itemData.item.department}}</span>
                        <span class="demo-FilterSearch__title">{{itemTemplate.itemData.item.owner}}<span class="demo-FilterSearch__iconDep icon-16 icon-Company icon-disabled"></span> (78)</span>
                    </div>
                </ws:contentTemplate>
            </ws:partial>
        </ws:itemTemplate>
    </Controls.list:View>
  2. Чтобы связать контролы между собой и обеспечить передачу данных нашим представлениям, оборачиваем их в контролы-контейнеры, соответственно, в Controls/search:InputContainer, Controls/filter:FastContainer, Controls/filter:ViewContainer и Controls/list:Container:
    <!-- WML -->
    <Controls.search:InputContainer>
        <Controls.search:Input ... />
    </Controls.search:InputContainer>
     
    <Controls.filter:FastContainer>
        <Controls.filter:FastFilter ... />
    </Controls.filter:FastContainer>
     
    <Controls.filter:ViewContainer>
        <Controls.filter:View ... />
    </Controls.filter:ViewContainer>
     
    <Controls.list:Container> 
        <Controls.list:View>
            ...
        </Controls.list:View>
    </Controls.list:Container>
  3. Для организации фильтрации и поиска помещаем "заполненные" контейнеры в контроллер Controls/search:Controller, который, в свою очередь, помещаем в контейнер Controls/list:DataContainer:
    <!-- WML -->
    <Controls.list:DataContainer source="{{_source}}" navigation="{{_navigation}}" keyProperty="id">
        <Controls.search:Controller searchParam="department">
            <div>
                 
                <Controls.search:InputContainer ... />
                 
                <Controls.filter:FastContainer ... />
                 
                <Controls.filter:ViewContainer ... />
                 
                <Controls.list:Container />
                 
            </div>
        </Controls.search:Controller>
    </Controls.list:DataContainer>
  4. Контейнер Controls/list:DataContainer помещаем в контроллер Controls/filter:Controller:
    <!-- WML -->
    <Controls.filter:Controller bind:filter="_filterSearch" fastFilterSource="{{_fastFilterData}}" filterButtonSource="{{_filterButtonData}}">
         
        <Controls.list:DataContainer>
            ...
        </Controls.list:DataContainer>
         
    </Controls.filter:Controller >

Здесь следует отметить, что параметры фильтрации настраиваем на Controls/filter:Controller.

Более подробно конфигурацию можно посмотреть в приведенном ниже демонстрационном примере.

Демонстрационный пример

Итог

  • Мы получили набор контролов, которые никак не связаны между собой, и могут лежать на разных уровнях вложенности в приложении.
  • Wasaby не предлагает контроллеров в традиционном понимании, но предоставляет другой способ разделения представления и поведения.
  • Контролы-контейнеры выполняют роль контроллеров в традиционной модели MVC.