FENOM'енальный курс. Часть 4. Выводим товары в категории с помощью mSearch2.

Шаблон MAGAZINE вы можете скачать по ссылке.

Друзья, сегодня мы с вами сделаем вывод товаров в категорию с помощью снипета mFilter2, который идет в компоненте mSearch2. Данный компонент платный, но я советую вам его приобрести. Если у вас по каким-то причинам это сделать не получается, то вы можете сделать аналогичный вывод товаров, используя pdoPage.

Конечно, чтобы нам вывести товары в категориях, их сначала необходимо создать. Что я и сделал. Сначала я создал несколько брендов:

FENOM'енальный курс. Часть 4. Выводим товары в категории с помощью mSearch2.

Создал несколько опций товаров и подкатегории, чтобы нам было что выводить:

FENOM'енальный курс. Часть 4. Выводим товары в категории с помощью mSearch2.

И, конечно, нужно создать товары. Я создал 27 товаров из разных ниш:

FENOM'енальный курс. Часть 4. Выводим товары в категории с помощью mSearch2.

Что ж приступим! Для начала предлагаю вам создать чанк для вывода товара, который я называл productTpl, для этого создаем файл в директории core/elements/chunks со следующим содержимым:

<!-- item -->
<div class="col-xl-4 col-lg-6 col-md-6 item-wrap">
  <div class="item eqh">
	<div class="image">
	  <div class="labels">
		{if $favorite?}
		<div>
		  <span class="labels-hits">Хит продаж</span>
		</div>
		{/if}
		{if $new?}
		<div>
		  <span class="labels-new">Новинка</span>
		</div>
		{/if}
		{if $old_price > 0?}
		<div>
		  <span class="labels-action">Акция</span>
		</div>
		{/if}
	  </div>
	  <div class="bigger">
		<a href="{$id | url}" class="text-center" style="display:block">
		  {if $image?}
			<img src="{$image}" alt="{$pagetitle | htmlent}" title="{$pagetitle | htmlent}" class="img-fluid">
		  {else}
			<img src="{$_modx->getPlaceholder('+noimage')}" alt="{$pagetitle | htmlent}" title="{$pagetitle | htmlent}" class="img-fluid">
		  {/if}
		</a>
		{if $_pls['vendor.logo']?}
			<img src="{$_pls['vendor.logo']}" class="vendor" alt="{$_pls['vendor.name']}">
		{/if}
	  </div>	  
	</div>
	<div class="text">
	  <a href="{$id | url}" class="title">{$pagetitle}</a>
	  <div class="features">
		
	  </div>
	  <div class="characters">
	    {$_modx->runSnippet('msProductOptions', [
			'onlyOptions' => $parent | resource: 'options',
			'product' => $id,
			'tpl' => '@FILE chunks/main_opts.tpl'
		])}
	  </div>
	  <div class="prices-block">
		<div class="prices">
		  {if $old_price > 0?}
		  <div class="old_price">
			<span>{$old_price}</span> <i class="fa fa-ruble"></i>
		  </div>
		  {/if}
		  {if $price > 0?}
		  <div class="price">
			<span>{$price}</span> <i class="fa fa-ruble"></i>
		  </div>
		  {/if}
		</div>
		<form method="post" class="ms2_form">
		  <input type="hidden" name="id" value="{$id}">
		  <input type="hidden" name="count" value="1">
		  <input type="hidden" name="options" value="[]">
		  <button type="submit" name="ms2_action" value="cart/add" class="btn btn-blue btn-rounded">В корзину</button>
		</form>
	  </div>
	</div>
  </div>
</div>
<!-- / item -->
	

Как вы уже успели заметить я не зря заполнял опции товаров, так как по нашему макету на каждой плашке карточки товара должны выводиться основные характеристики товара. Как мы их будем задавать? Я решил, что проще всего это будет сделать следующим образом:

  • создать TV-параметр options и привязать его к шаблону “Каталог товаров”
  • и для дочерних товаров выводить только те опции, которые указаны в TV

За вывод данного блока у нас отвечает конструкция:

{$_modx->runSnippet('msProductOptions', [
	'onlyOptions' => $parent | resource: 'options',
	'product' => $id,
	'tpl' => '@FILE chunks/main_opts.tpl'
])}
	

Подробно по каждому из параметров я расскажу в видео. И собственно, чанк main_opts.tpl:

{foreach $options as $option}
	<div class="char-item">
	  <span class="label">{$option.caption}:</span>
	  <span class="value">
		{if $option.value is array}
			{$option.value | join : ', '}
			{if $option.measure_unit?}
				{$option.measure_unit}
			{/if}
		{else}
			{$option.value}
			{if $option.measure_unit?}
				{$option.measure_unit}
			{/if}
		{/if}
	  </span>
	</div>
{/foreach}
	

Кстати, именно на этом чанке видно основное преимущество Fenom над стандартным шаблонизатором MODx: чанков становится на порядок меньше. Мы с вами в прошлом курсе уже разбирали как делать фильтр на mSearch2, думаю, что вы легко справитесь с предстоящей задачей.

Создадим с вами первый чанк mfilter_outer.tpl (я напоминаю, что все чанки у нас хранятся в файлах):

<div class="row msearch2" id="mse2_mfilter">
    <div class="col-lg-3">
        <div class="sidebar">
            <!-- widget -->
            <div class="widget filters">
                <span class="title">Фильтр</span>
                <div class="widget-content">
                    <form action="{$id | url}" method="post" id="mse2_filters">
                        {$filters}
                    </form>
                </div>
            </div>
            <!-- / widget -->
        </div>
    </div>
    <div class="col-lg-9">
        <div class="product-list">
            <div class="row" id="mse2_results">
                {$results}
            </div>
            <div class="paging mse2_pagination">
                <nav>
                    {'page.nav' | placeholder}
                </nav>
            </div>
        </div>
    </div>
</div>
	

Обратите особое внимание на классы и идентификаторы, которые прописаны в чанке. Теперь нам можно попробовать сделать вызов mFilter2 в шаблоне:

{$_modx->runSnippet('!mFilter2', [
	'element' => 'msProducts',
	'class' => 'msProduct',
	'showEmptyFilters' => 1,
	'limit' => 9,
	'tplOuter' => '@FILE chunks/mfilter_outer.tpl',
	'tplPageWrapper' => '@INLINE <ul class="pagination">{$prev}{$pages}{$next}</ul>',
	'tplPageActive' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">{$pageNo}</a></li>',
	'tplPage' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">{$pageNo}</a></li>',
	'tplPagePrev' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">«</a></li>',
	'tplPageNext' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">»</a></li>',
	'tplPagePrevEmpty' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">«</a></li>',
	'tplPageNextEmpty' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">»</a></li>',
	'filters' => 'msoption|sndvvatt,
				msoption|sndvvolume,
				ms|price:number,
				msoption|pokroi,
				msoption|rukzkolvootd,
				msoption|rukzvolume,
				msoption|smartobpam,
				msoption|smartoppam',
	'aliases' => 'msoption|sndvvatt==sndvvatt,
				msoption|sndvvolume==sndvvolume,
				ms|price==price,
				msoption|pokroi==pokroi,
				msoption|rukzkolvootd==rukzkolvootd,
				msoption|rukzvolume==rukzvolume,
				msoption|smartobpam==smartobpam,
				msoption|smartoppam==smartoppam',
	'ajaxMode' => 'button',
	'filterOptions' => '{
			"more_tpl": "<div class=\"text-center\"><button class=\"btn btn-blue btn-rounded btn_more\">Загрузить еще</button></div>"
			}',
	'tpls' => '@FILE chunks/product_tpl.tpl',
])}
	

Нам с вами осталось привести в порядок фильтры. Для начала мы с вами переведем все опции, которые у нас не переведены. Для этого переходим в “Управление словарями”, выбираем топик “mSearch2” и язык “RU”. И добавляем наши опции:

FENOM&#39;енальный курс. Часть 4. Выводим товары в категории с помощью mSearch2.

После перевода нам нужно добавить еще 4 параметра в вызов mFilter2. Эти параметры, как вы уже догадались, чанки, которые нам также необходимо создать в папке core/elements/chunks. Вызов mFilter2 у нас приобретет следующий вид:

{$_modx->runSnippet('!mFilter2', [
	'element' => 'msProducts',
	'class' => 'msProduct',
	'showEmptyFilters' => 1,
	'limit' => 9,
	'tplOuter' => '@FILE chunks/mfilter_outer.tpl',
	'tplPageWrapper' => '@INLINE <ul class="pagination">{$prev}{$pages}{$next}</ul>',
	'tplPageActive' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">{$pageNo}</a></li>',
	'tplPage' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">{$pageNo}</a></li>',
	'tplPagePrev' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">«</a></li>',
	'tplPageNext' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">»</a></li>',
	'tplPagePrevEmpty' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">«</a></li>',
	'tplPageNextEmpty' => '@INLINE <li class="page-item"><a class="page-link" href="{$href}">»</a></li>',
	'filters' => 'msoption|sndvvatt,
				msoption|sndvvolume,
				ms|price:number,
				msoption|pokroi,
				msoption|rukzkolvootd,
				msoption|rukzvolume,
				msoption|smartobpam,
				msoption|smartoppam',
	'aliases' => 'msoption|sndvvatt==sndvvatt,
				msoption|sndvvolume==sndvvolume,
				ms|price==price,
				msoption|pokroi==pokroi,
				msoption|rukzkolvootd==rukzkolvootd,
				msoption|rukzvolume==rukzvolume,
				msoption|smartobpam==smartobpam,
				msoption|smartoppam==smartoppam',
	'ajaxMode' => 'button',
	'filterOptions' => '{
			"more_tpl": "<div class=\"text-center\"><button class=\"btn btn-blue btn-rounded btn_more\">Загрузить еще</button></div>"
			}',
	'tpls' => '@FILE chunks/product_tpl.tpl',
	'tplFilter.outer.default' => '@FILE chunks/filter_outer.tpl',
	'tplFilter.row.default' => '@FILE chunks/filter_row.tpl',
	'tplFilter.outer.price' => '@FILE chunks/filter_outer_price.tpl',
	'tplFilter.row.price' => '@FILE chunks/filter_row_price.tpl'
])}
	

Чанк filter_outer.tpl – это стандартная обертка для наших фильтров:

<div class="widget-filter" id="mse2_{$table}{$delimeter}{$filter}">
    <h4 class="filters-title">{$_modx->lexicon('mse2_filter_'~$table~'_'~$filter)}</h4>
    <div class="widget-content">
        {$rows}
    </div>
</div>
	

Чанк filter_row.tpl – это вывод опции в виде чекбокса:

<div class="custom-control custom-checkbox">
    <input type="checkbox" name="{$filter_key}" id="mse2_{$table}{$delimeter}{$filter}_{$idx}"  value="{$value}" {$checked} {$disabled} class="custom-control-input">
    <label for="mse2_{$table}{$delimeter}{$filter}_{$idx}" class="{$disabled} custom-control-label">
        {$title}
    </label>
</div>
	

Чанк filter_outer_price.tpl – обертка для фильтра цены (в виде слайдера):

<div class="widget-filter" id="mse2_{$table}{$delimeter}{$filter}">
    <h4 class="filters-title">{$_modx->lexicon('mse2_filter_'~$table~'_'~$filter)}</h4>
    <div class="widget-content">
        <fieldset>
            <div class="mse2_number_inputs row">
        		{$rows}
        	</div>
            <div class="mse2_number_slider"></div>
    	</fieldset>
    </div>
</div>
	

Чанк filter_row_price.tpl – это элемент при выводе слайдера цены (минимальное и максимальное значение):

<div class="col-6">
	<label for="mse2_{$table}{$delimeter}{$filter}_{$idx}">{$title}		
        <input type="text" name="{$filter_key}" id="mse2_{$table}{$delimeter}{$filter}_{$idx}" value="{$value}">
	</label>
</div>
	

Как видите все достаточно просто. Мы с вами реализовали вывод товаров в категории. Если вы попытаетесь кликнуть по кнопке “В корзину”, товар туда добавится. На этом мы с вами закончим нашу 4 часть.

FENOM'енальный курс. Часть 4. Выводим товары в категории с помощью mSearch2.

0 Число голосов: 5
5
5
1
5

Комментарии ()

  1. vk 04 августа 2019, 01:02 # 0
    Добрый вечер,имя первого файла не productTpl, а согласно вызову product_tpl.С уважением.
    1. vk 04 августа 2019, 01:04 # 0
      Добрый вечер,Имя первого шаблона product_tpl.tpl как стоит в вызове.С уважением.
      1. Serge Rosolovsky 23 сентября 2019, 22:27(Комментарий был изменён) # 0
        action="{$id | url}" вот это будет давать пустой action в форме!!!
        1. Roman 10 мая 2020, 16:30 # 0
          Здравствуйте, подскажите как исправить пегинацию'ajaxMode' => 'button', 'filterOptions' => '{ «more_tpl»: "<button class=\«btn btn-blue btn-rounded btn_more\»>Загрузить еще" }',выдает ошибку и на Вашем тестовом сайте такжеdefault.js:608 Uncaught TypeError: Cannot read property 'serializeArray' of undefined at Object.getFilters (VM11816 default.js:608) at HTMLAnchorElement.(VM11816 default.js:985) at Function.each (jquery.min.js:2) at n.fn.init.each (jquery.min.js:2) at Object.addPage (VM11816 default.js:979) at HTMLButtonElement.(VM11816 default.js:199) at HTMLDocument.dispatch (jquery.min.js:3) at HTMLDocument.r.handle (jquery.min.js:3)

          Наши клиенты

          Многие компании уже доверяют нам. Будьте в их числе!

          Хотите реализовать проект?

          Контакты

          Напишите нам - мы расскажем вам много интересного!


          Пермь, ул. Крупской 34, офис 510