Создание гибкого каталога с фильтрами (list)

В проекте можно реализовать несколько универсальных каталогов со своей разметкой (товары, исполнители, заказы, проекты, портфолио и т.д). 

Расположены каталоги по адресу /list/{code}

Вид каталога по умолчанию такой (слева категории и фильтры, по центру - основные элементы):

Формат URL категории

Формат URL категории с фильтрами

Формат URL товара

Управление выведено в Компоненты / Универсальные каталоги - /aslists

Таблица as_lists

Процедура list_{code}_search - вывод элементов каталога (список)

На входе: 

На выходе множество SELECT, на основе которых осуществляется вывод каталога: 

SELECT 1 результаты операции 

SELECT 2 Фильтры каталога слева (ID, Code, Title, Tooltip, TypeCode, DefValue, ShowCount, CommaValues, CommaSelected, Options, Placeholder)

SELECT 3 Дерево категорий, показывающих текущее положение в каталоге (ID, Code, Name, Level, URL, ParentID, Count)

SELECT 4 Вложенные категории  (ID, Code, Name, Level, URL, ParentID, Count)

SELECT 5 Элементы каталога (ID, Name, Desc, Price, Url, ImgUrl)

SELECT 6 Параметры элементов каталога  (ID, Code, Name, Value, ItemID)

SELECT 7 Дополнительные атрибуты для вывода на странице поиска  (ID, Code, Name, Value)

SELECT 8 Варианты сортировок (Key, Value)

SELECT 9 Начальное меню категорий (может выводиться наверху перед поиском, например, в самом корне каталога). 

Примечание: 

CREATE PROCEDURE [dbo].[list_new_search]
	@filters DictionaryParameter READONLY,
	@cats nvarchar(256),
	@sort nvarchar(24),
	@page int,
	@username nvarchar(32)
AS
BEGIN
	-- ПРОЦЕДУРА ПОИСКА ПО УНИВЕРСАЛЬНОМУ КАТАЛОГУ
        /*Определяем какие фильтры есть в url, и с учетом этого
          отбираем элементы для каталога*/

	-- Для пагинации
	declare @PAGE_SIZE int = 10, @total int = 0
        /*Сохраняем ID элементов каталога во временной таблице.
          Подсчитываем сразу полученное количество*/
	declare @itemIDs table (id int)

      /*Находим, на какой категории мы сейчас стоим, в общем дереве категорий
      @cats - это часть url где указаны категории, например для
       /list/suppliers/category1/category1_1/category1_1_3 будет @cats =
      'category1,category1_1,category1_1_3'*/

	CREATE TABLE dbo.#cats (id int, code nvarchar(256), name nvarchar(256), level
                                int, parentID int)
	insert into #cats
	select id, code, name, 1 [level], parentID
        from au_projectCategories
        where code in (select Value from dbo.split(@cats, ','))

	-- Выбранных категорий может быть несколько, с учетом вложенности вложенность
	declare @catCount int
	select @catCount = count(*) from #cats
	/* Находим конечную точку в дереве на которой остановились, то есть
           максимального уровня (в примере выше это будет category1_1_3)*/
	declare @selectedCatID int
	select top 1 @selectedCatID = id from #cats order by level desc

    -- Обработка возможных фильтров
    -- declare @filterCity nvarchar(256)
    -- select @filterCity = Value from @filters where [Key] = 'city'

    --- добавляем сортировку в Динамический запрос SELECT 1
    declare @sortStatement nvarchar(512)
    set @sortStatement = (case @sort
                    when 'rating' then ' order by name '
                    end	)

    -- Итак, что находим учитывая выбранные категории и отмеченные фильтры?
    insert into @itemIDs
    select distinct id
      from (select id, 111 catID
              from au_suppliers) t
    -- Категории поставщика входящие в выбранные категории, или в дочерние категории выбранных категорий
	where (isnull(@cats,'')='' or t.catID = @selectedCatID
            					or (select parentID from au_projectCategories where id = t.catID) = @selectedCatID )

	select @total = count(*) from @itemIDs

	-- SELECT 1 - SearchItemsResult (настройки поиска, общие параметры каталога)
	select 'Не найдено' EmptyText,
		   (case when isnull(@cats,'')='' then 'Каталог поставщиков услуг' else (select name from au_projectCategories where id = @selectedCatID) end) Title,
		   'desc' Text,
		   @sort Sort,
		   @page [Page],
		   @PAGE_SIZE PageSize,
		   @total Total,
		   'DEMO' SeoTitle,
		   'DEMO' SeoDescription,
		   'DEMO' SeoKeywords,
		   ''  HeadSection,
		   ''  BodyBottomSection,
		   1 Result,
  iif(@langID=1, 'SQL Server', 'SQL Server')  BreadcrumbRootTitle,
           iif(@langID=1, 'Home', 'Главная')+'||/' preBreadcrumbs,
            '' rightBreadcrumb,
            '' redirectUrl,
           301 redirectStatusCode,
           '' Msg
	-- SELECT 2 - FilterParameter - Показываем либо все услуги, либо относящиеся к выбранной категории
	select 1
    /*select 0 id,
    	   'Город' title,
		   'Город' tooltip,
		   'city' Code,
		   '' defValue,
		   'checks' typeCode,
		   (select stuff( (
						select ','+ name
						  from (select name from as_geo_regions) t1
						for xml path(''), type
						   ).value('.', 'varchar(max)'), 1, 1, ''
						 )
			) as  commaValues,
		   (select top 1 Value from @filters where [Key] = 'city') commaSelected,
3 showCount
*/

	-- SELECT 3 - Cat  CatChain - Выбранные категории
	select * from #cats order by level
	-- SELECT 4 - Cat  InnerCats - отобразим сбоку либо все категории, либо категории входящие в выбранную
    select *
    from au_projectCategories
	where parentID = @selectedCatID or (parentID is null and @catCount = 0)

	drop table #cats

	-- SELECT 5 - Item (ID, Desc, Price, Name, URL) -- Данные отображаемые в перечне элементов каталога
	select s.id,
		  isnull(surname+' '+firstname+' '+lastname, username) as name,
          '' [desc],
          '0' price,
          '/list/test/'+isnull(c.username,'')+'---'+try_cast(s.id as nvarchar) Url
	 from au_suppliers s join ctr_contacts c on c.id = s.contactID
     where s.id in (select id from @itemIDs)

	-- SELECT 6 - ItemParam
    -- Атрибуты элементов каталога
    -- Структура Атрибута: ID, Name, Code, Value, ItemID
    -- В разметке listItemMakeup атрибут отобразится по {param-code}
	select 1 as ID, 'Категории услуг' as Name, 'categories' as Code,
    	   'value1' as Value, 111 as ItemID
    union

    select 2 as ID,
    'О себе' as Name,
    'description' as Code,
    (select isnull(description,'О себе') from ctr_contacts where id = contactID) as value,
    id as ItemID  from au_suppliers

	-- SELECT 7 - Param общие Атрибуты для каталога (ID, Name, Code, Value)
    -- Атрибуты самого каталога
    -- Структура Атрибута: ID, Name, Code, Value
    -- В разметке listMakeup атрибут отобразится по {param-code}
	select 1

	-- SELECT 8 - DictionaryParameter  Sorts
	select 'rating' [key], 'По рейтингу' Value

	-- select 9 -- Start cats (категории которые показываются на 1 экране каталога как дашборд {catList})
	select id, code, name, 1 level, parentID,'' [Image],
    'fas fa-wrench' iconClass
	  from au_projectCategories where @selectedCatID is null and (parentID is null or parentID in (select id from au_projectCategories where parentID is null) )
END

 

Процедура list_{code}_getItem - вывод карточки одного элемента каталога (страница товара)

Входные параметры: 

  1. @itemID - ID элемента 
  2. @username - текущий пользователь
  3. @parameters ExtendedDictionaryParameter readonly - опционально, содержит langID, falconGuid, url (только часть после /list/{code}/) и другие  параметры в виде Key, Value2

Результат работы процедуры GetItem: 

SELECT 1  Данные по выбранному элементу 

SELECT 2  Иерархия категорий к данному элементу, путь по категориям (ID, Code, Name, Level, URL, ParentID, Count)

SELECT 3  Дополнительные атрибуты элемента в виде таблицы (ID, Code, Name, Value, ItemID)

SELECT 4-8 Кастомные списки (используются только параметры с названиями p1, p2, p3, p4, p5, p6)

Примеры процедуры GetItem https://pastebin.com/WJFMKYTT

Примечание: 

Разметка as_lists: listMakeup - разметка каркаса страницы каталога

 Параметры (используются как {name}):

Разметка as_lists: listItemMakeup - разметка 1 элемента в каталоге (на странице поиска)

Параметры (использовать как {code}):

Разметка as_lists: itemDetailsMakeup - разметка карточки элемента (на странице товара)

Параметры (использовать как {code}):

Примечания по каталогам List

 

Howto по каталогам List

Как добавить микроразметку, стили или скрипты в каталог.

Используйте параметры headSection, bodyBottomSection в SELECT 2 в list_search и аналогичные параметры в  list_getItem. Вы можете туда вставлять коды OpenGraph и JSON LD описание страниц.

Как динамически изменить корень хлебных крошек? 

Используйте параметр BreadcrumbRootTitle в SELECT 2 в list_search и аналогичные параметры в  list_getItem. 

Главное применение - при локализации каталога. 

Также можно добавить дополнительные элементы перед корнем каталога с помощью параметра preBreadcrumbs (задается в виде name1||url1,name2||url2 -т.е. будет добавлено 2 элемента в начало списка (в названии не должно быть запятых)).

Как сделать другое число скрываемых параметров в фильтре?

Для этого необходимо установить для фильтров в SELECT 2 процедуры search параметр showCount (по умолчанию 4).  Эта настройка работает для типов фильтра radio, checks.

Как сделать так чтобы фильтры с Not Selected (или не выбрано) не попадали в адрес?

Для этого на страницу надо добавить подобную разметку и перечислить все значения  по умолчанию во вложенных элементах span 

<div class="cat-notSelectedList">
	<span data-value="--"></span>
    <span data-value="Not selected"></span>
	<span data-value="Не выбрано"></span>
</div>

Как сделать так, чтобы вложенные категории наследовали установленные фильтры

Для этого укажите настройку  с кодом listAppendFiltersToCatUrl = 1.

Важно при этом, чтобы URL в SELECT 4 приходил пустым (платформа формирует URL для внутренних категорий, только если он не передан в явном виде).

Как настроить кеширование списка List

Для этого установите в WebConfig в разделе AppSettings параметр listCacheMinutes. Данный параметр указывает сколько минут будет кешироваться результат выдачи в списке List
(кешируются все запросы по списку - вариации выбора фильтров и категорий).

Как работать с типом фильтра Цвет color

Для этого указываем в select 2 в Search процедуре
  select 3 id,
    	   'Цвета' title,
		   'Имеется ссылка либо на прототип либо дополнительный скрин' tooltip,
		   'filterColor' Code,
		   '' defValue,
		   'color' typeCode,
		   '#ccc,#a00,#0f0' as  commaValues,
		   (select top 1 Value from @filters where [Key] = 'filterColor') commaSelected
    
Примечание. В URL передается цвет без #. Но в обработке можно использовать формат #abc или #aabbcc

Как работать с типом фильтра Диапазон чисел range

Как выглядит: 

в SELECT 2 процедуры search:

 select 3 id,
    	  'Slider' title, 
		   'Slider1' tooltip, 
		   'range1' Code,
		   '' defValue, 
		   'range' typeCode,
		   '10,100,5' as  commaValues,
		   (select top 1 Value from @filters where [Key] = 'range1') commaSelected
    

В CommaValues задаем min,max,step значения. 

Как работать с типами фильтра Групповые кнопки (одиночный и множественный выбор) checkButtons

Для этого используем типы checkbuttons (множественный выбор) и radiobuttons (одиночный выбор).

В SELECT 2 процедуры search: 

 select 3 id,
    	   'Категория' title, 
		   '111' tooltip, 
		   'cat1' Code,
		   '' defValue, 
		   'checkbuttons' typeCode,
		   ('12,421333124,52131235,61231221316,77') as  commaValues,
		   (select top 1 Value from @filters where [Key] = 'cat1') commaSelected  
  

Дополнительную стилизацию кнопок можно сделать через CSS. 

Как использовать спецсимволы в имени фильтра

Бывает ситуация, когда в значениях фильтров идут специальные символы, которые недопустимы в URL (например, +.#&). В этом случае в SELECT 2 необходимо передавать Values как значения как code||name.

-- SELECT 2 in SEARCH
 select 2 id,
    	   'Stacks' title,
		   '' tooltip,
		   'stack' Code,
		   '' defValue,
		   'select' typeCode,
		   (select 'Not selected,' +
            stuff((select top 3000 ',' + code + '||'+ name
				   from rg_stacks order by name
				   for xml path(''), type).value('.', 'nvarchar(max)'), 1, 1, '')) as commaValues,
		   (select top 1 Value from @filters where [Key] = 'stack') commaSelected,

Также при проверке на существование фильтра проверяйте на code (а не на выводимый name).

Таким образом необходимо заранее обработать значение на спецсимволы и хранить в отдельном поле в справочнике (например, в поле code) и использовать его для работы фильтра.
Примечание: теги также используют по умолчанию выводимое (соответствует name) и скрытое значение (соответствует code)

Страница-источник на сайте falconspace.ru