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

Смотреть видео

В проекте можно реализовать несколько универсальных каталогов со своей разметкой. Программно это совсем другой тип работы каталога, со своей схемой реализации.

  • Каталогов на одном домене может быть несколько, все они хранятся в as_lists, каждый имеет свою разметку, и свои процедуры search и getItem.
  • Такие каталоги не привязаны жёстко к базе. Таким образом, выступать в роли Категорий и Фильтров могут абсолютно разные данные (а не as_cat_categories и as_cat_filters как в варианте выше).
  • Сохранение URL элемента каталога необходимо реализовать самостоятельно.

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

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

  • /list/{code}/{category1}/{category2}

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

  • /list/{code}/{category1}/{category2}/f/{filter1}-{text1},{text2}/{filter2}-{text3}/{filter3}-{text4}

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

  • /list/{code}/{category1}/{category2}/p/{url элемента каталога}

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

Таблица as_lists

  • id - id каталога
  • code - код каталога
  • rootURL - код каталога в URL (ВАЖНО - прописываем просто кодовое название, например, services, а не полный URL)
  • listMakeup - HTML разметка каталога
  • listItemMakeup - HTML разметка списковой части каталога (элементов)
  • itemDetailsMakeup - HTML разметка страницы элемента каталога

Процедура list_{code}_search

На входе: 

  • filters - значения фильтров (Key,Value). Также здесь передается langID для перевода на языки.
  • cats  - id дерева выбранных категорий через запятую
  • sort - по какому полю сортировка
  • page - номер страницы (для организации пагинации)
  • username - текущий пользователь
  • parameters ExtendedDictionaryParameter readonly - опционально, содержит langID, falconGuid, url (только часть после /list/{code}/) и другие параметры в виде Key, Value2

На выходе: 

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

  • Result - результат операции 
  • Msg - сообщение при ошибке
  • EmptyText - вывод сообщения, когда ничего не найдено
  • Title - тег h1
  • Text - текст на странице (например, описание категории)
  • Sort - текущая сортировка
  • SortView - тип вывода элемента сортировки (по умолчанию кнопки). Если указать select (или select2) - то выбор будет в виде выпадающего списка
  • Page, PageSize, Total - данные для пагинации (номер страницы, размер пейджинга, всего элементов)
  • SeoTitle, SeoDescription, SeoKeywords - seo данные по странице (title, meta keywords, meta description)
  • HeadSection - разметка в разделе head (например, можно добавить микроразметку)
  • BodyBottomSection - разметка перед закрывающим тегом body (здесь можно подключить скрипты)
  • BreadcrumbRootTitle - название корневого элемента каталога
  • PreBreadcrumbs - дополнительные элементы впереди в хлебных крошках в формате name1||url1,name2||url2
  • RightBreadcrumb - разметка для вставки в хлебные крошки справа (вспомогательные ссылки)
  • RightBreadcrumbDropdownMakeup - некая HTML разметка всплывающей панели в хлебных крошках справа
  • RedirectUrl, RedirectStatusCode - если указан адрес, то страница сделает редирект с указанным статусом
  • LandMakeup - разметка страницы с внешним каркаcом (с body, html, head). Подробнее - как сделать каталог с внешней разметкой.

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 Начальное меню категорий (может выводиться наверху перед поиском, например, в самом корне каталога). 

  • ID
  • Name - название
  • Code  код категории
  • URL - путь к категории
  • Image - картинка URL 
  • IconClass - иконка 
  • ParentID родительская категория 
  • Count - количество элементов в категории

Примечание: 

  • Типы фильтров( typeCode из SELECT 2):
    • checks - галочки (в процедуру передаются как строка со значениями через запятую)
    • radio - радио-переключатели
    • select, select2 - выбор из списка с поиском
    • selectmultiple, select2multiple - множественный выбор из списка (в процедуру передаются как строка со значениями через запятую)
    • switch - переключатель да-нет
    • text - строка для ввода
    • color - выбор цвета
    • range - выбор диапазона
    • radiobuttons - кнопки для одиночного выбора
    • checkbuttons - кнопки для множественного выбора
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  Данные по выбранному элементу 

  • ID - ID элемента
  • Name - наименование (тег h1)
  • Price - стоимость
  • Desc - текст с описанием
  • ImgUrl - URL картинки элемента
  • SeoTitle, SeoDescription, SeoKeywords - SEO данные по странице
  • HeadSection - разметка в разделе head (например, микроразметка)
  • BodyBottomSection - разметка перед закрывающим тегом body (сюда можно добавить подключение скриптов)
  • List1Makeup, List2Makeup, List3Makeup, List4Makeup, List5Makeup - разметка дополнительных списков (выводится разметка как {list1}, задействует элементы из SELECT 4-8 как {p1}-, использовать можно только эти предопределенные названия атрибутов).
  • BreadcrumbRootTitle - название корневого элемента каталога
  • PreBreadcrumbs - дополнительные элементы впереди в хлебных крошках в формате name1||url1,name2||url2
  • RightBreadcrumb - разметка для вставки в хлебные крошки справа (вспомогательные ссылки)
  • RightBreadcrumbDropdownMakeup - некая HTML разметка всплывающей панели в хлебных крошках справа
  • RedirectUrl, RedirectStatusCode - если указан адрес, то страница сделает редирект с указанным статусом
  • LandMakeup - разметка страницы с внешним каркаcом (с body, html, head). Подробнее - как сделать каталог с внешней разметкой.
  • itemsClass, itemClass - CSS классы для контейнеров всего каталога и 1 элемента (иногда требуется установить для этих блоков свои классы, например row). 

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

Примечание: 

  • в процедуру может передаваться также необязательный параметр @parameters (тип DictionaryParameter), в котором передается langID
  • Процедуру можно найти в демо проекте.

Разметка as_lists: listMakeup

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

  • filtes - вставка  фильтров
  • innerCats - категории в текущей категории
  • cats - дерево категорий до текущей категории
  • tags - теги для отображения выбранных фильтров
  • viewTypes - 2 вида просмотра каталога
  • title - заголовок каталога
  • foundCount - метка количества результатов
  • desc - описание текущей категории
  • sorts - элемент управления сортировкой
  • items - вывод элементов каталога
  • paging - элемент управления пагинацией
  • {param-code} - вставка дополнительных параметров
  • {filter-code} - можно также разместить каждый фильтр отдельно. 
    ВАЖНО. Обязательно указывайте {cats}, он необходим для построения адресов. Если не нужно его выводить, используйте div с классом hide с содержимым {cats}.  
    {cats} в контейнере с классом hide. Также обязательно должна быть кнопка поиска (можно скрытую) - даже в случае режима instantFilter.   Т.е. просто помещаем эти системные элементы в div class="hide".

Разметка as_lists: listItemMakeup

 

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

  • id - ID элемента
  • name - наименование элемента
  • desc - описание элемента
  • price - цена
  • url - URL страницы элемента
  • imgUrl - картинка элемента
  • addToCart - кнопка добавления в корзину
  • addToFav - кнопка добавления в избранное
  • param-[code] - дополнительные параметры, переданные через sql
  • image - картинка элемента (как image-resource)

Разметка as_lists: itemDetailsMakeup

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

  • id - ID элемента
  • name - наименование элемента
  • desc - описание элемента
  • imgUrl - картинка элемента
  • price - цена
  • addToCart - кнопка добавления в корзину
  • addToFav - кнопка добавления в избранное
  • param-[code] - дополнительные параметры, переданные через sql
  • images - галерея картинок элемента
  • list1-list5 (с параметрами p1-p6) - вывод дополнительных списков (их разметка задается в соответствующих параметрах в хранимых процедурах List1Makeup-List5Makeup). 

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

  • Для категорий вы можете также указывать Url параметр и тогда именно он будет браться за основу, а не строить по иерархическому принципу (вложенность категорий).
  • Можно делать innerCats постоянным (т.е. чтобы всегда категории выводились одни и те же, даже когда мы находимся в одной из них). При этом текущая категория будет выделяться (идет проверка по вхождению URL в текущий адрес страницы). Делайте уникальные названия категорий без возможных пересечений (например car и carPlaces - плохие названия категорий, т.к. одно входит в другое название).
  • Везде по проекту для получения ссылок на карточку или категорию каталога используйте функции list_getProductURL и list_getCatURL соответственно. Это уменьшит риск битых ссылок и упростит в будущем возможную дополнительную обработку адресов. 

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

Используйте параметры 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

Фильтр для диапазона чисел

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

в 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 (множественный выбор) и 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)

Falcon Space - функциональная веб-платформа разработки на узком стеке MS SQL/Bootstrap. Вводная по Falcon Space
Насколько полезной была статья?

Google поиск по нашей документации

Выгода от использования Falcon Space

В 2-3 раза экономнее и быстрее, чем заказная разработка
Более гибкая, чем коробочные решения и облачные сервисы
Используйте готовые решения и изменяйте под свои потребности
Нужна бесплатная консультация?
Планируете делать веб-проект?
Сайт использует Cookie. Правила конфиденциальности OK