В админке битрикса есть довольно удобный и красивый способ выбора элементов инфоблока.
Используется он в модуле маркетинга, при выборе товаров в редактировании скидки.
И использовать его оказалось довольно просто. За это окошко отвечает компонент bitrix:catalog.product.search.
В админке есть страница /bitrix/modules/catalog/admin/cat_product_search_dialog.php, в ней лежит вызов компонента:
Который и отрисовывает это кошко.
Как использовать
Вызов окна работает на js, поэтому создадим класс, отвечающий за вызов окна и обработку его результатов.
Разберем методы и параметры.
getDefaultProps - Выдает дефолтные параметры
event: 'onSelectElement' - это кастомное событие, на которое мы будем вешаться, дабы отследить, что в окошке выбрали товар. Писать там можно что угодно, хоть hrenMorjovii.
lang: 'ru' - язык сайта.
allow_select_parent: 'Y' - не экспериментировал особо с этим параметром, за что отвечает - хз. Без него тоже работает.
compileUrl - комплит урл, по которому надо получать контент окна. По сути, впихивает в урл все props, которые у нас есть.
/bitrix/admin/esd_element_search_dialog.php - кастомная страница вызова компонента, которую мы создали, и положили вызов компонента, аналогично /bitrix/modules/catalog/admin/cat_product_search_dialog.php
dialogSearch - формирует объект админского диалогового окна. Подробности тут и как всегда в исходниках /bitrix/js/main/core/core_window.js.
У этого объекта есть параметр content_url, если его указать, то контент в окно будет аяксом подтянут по этому урлу. Это нам и нужно.
И в файле, где нам это окно нужно использовать:
Параметр IBLOCK_ID - отвечает за тот инфоблок, с которого надо тянуть элементы.
Метод dialog.dialogSearch().getDialog().Show(); отвечает за показ окна. Я его здесь вызвал при отработке скрипта, но его можно обернуть в какой-нибудь onClick и вызывать в нем. Это уже люди сами разберутся, где и как юзать.
Для отслеживания выбора элементов повесимся на событие, которое мы указали в объекте.
По дефолту это окно выбирает только те инфоблоки, которые отмечены как торговые каталоги.
Если же нам надо выбрать вообще любой ИБ, то нужно кастомизировать компонент. Благо он сделан с использованием class.php.
Копируем компонент bitrix:catalog.product.search в свое пространство.
Пересоздаем class.php, вызываем в нем подключение родительского класса.
Переопределяем несколько методов.
checkIblockAccess() - чтоб не проверять, что у нас только каталоги и разрешать все ИБ.
getIblockList() - скажет компоненту, какие ИБ можно выбирать в окошке. Собственно, тут же можно сформировать свой список, если задача того требует.
getIblockId() - чтобы тоже избежать проверок на принадлежность ИБ к каталогу, и показывать ИБ из $_GET в изначальной отрисовке окна. Грубо говоря, чтоб в arParams['IBLOCK_ID'] попал ИБ, который мы в js засунули.
Далее, в админке, на своей странице меняем вызов компонента на свой. И в конструктор объекта можно передавать новый урл.
Листинг вызова окошка.
Используется он в модуле маркетинга, при выборе товаров в редактировании скидки.
И использовать его оказалось довольно просто. За это окошко отвечает компонент bitrix:catalog.product.search.
В админке есть страница /bitrix/modules/catalog/admin/cat_product_search_dialog.php, в ней лежит вызов компонента:
<?php
define("NO_KEEP_STATISTIC", true);
define('NO_AGENT_CHECK', true);
define("NO_AGENT_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS", true);
define('DisableEventsCheck', true);
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php");
global $APPLICATION;
$APPLICATION->ShowAjaxHead();
$APPLICATION->IncludeComponent("bitrix:catalog.product.search",'.default', [], false);
die();
|
Как использовать
Вызов окна работает на js, поэтому создадим класс, отвечающий за вызов окна и обработку его результатов.
"use strict";
class ElementSearch {
constructor(props){
this.props = Object.assign({}, this.getDefaultProps(), props);
this._dialogSearch = null;
}
getDefaultProps(){
return {
event: 'onSelectElement',
lang: 'ru',
allow_select_parent: 'Y',
url: '/bitrix/admin/esd_element_search_dialog.php'
}
}
compileUrl(){
return BX.util.add_url_param(this.props.url, this.props);
}
dialogSearch() {
this._dialogSearch = new BX.CDialog({
title: 'Поиск элементов',
width: 1350,
height: 800,
content_url: this.compileUrl(),
ESD: true
});
this._dialogSearch.SetButtons([{
title: BX.message('JS_CORE_WINDOW_SAVE'),
id: 'savebtn',
name: 'savebtn',
className: BX.browser.IsIE() && BX.browser.IsDoctype() && !BX.browser.IsIE10() ? '' : 'adm-btn-save',
action: () => {
this._dialogSearch.Close();
}
}]);
return this;
}
getDialog(){
return this._dialogSearch
}
getEvent(){
return this.props.event;
}
}
export default ElementSearch;
|
getDefaultProps - Выдает дефолтные параметры
event: 'onSelectElement' - это кастомное событие, на которое мы будем вешаться, дабы отследить, что в окошке выбрали товар. Писать там можно что угодно, хоть hrenMorjovii.
lang: 'ru' - язык сайта.
allow_select_parent: 'Y' - не экспериментировал особо с этим параметром, за что отвечает - хз. Без него тоже работает.
compileUrl - комплит урл, по которому надо получать контент окна. По сути, впихивает в урл все props, которые у нас есть.
/bitrix/admin/esd_element_search_dialog.php - кастомная страница вызова компонента, которую мы создали, и положили вызов компонента, аналогично /bitrix/modules/catalog/admin/cat_product_search_dialog.php
dialogSearch - формирует объект админского диалогового окна. Подробности тут и как всегда в исходниках /bitrix/js/main/core/core_window.js.
У этого объекта есть параметр content_url, если его указать, то контент в окно будет аяксом подтянут по этому урлу. Это нам и нужно.
И в файле, где нам это окно нужно использовать:
import ElementSearch from './ElementSearch';
const dialog = new ElementSearch({ IBLOCK_ID: 147 });
dialog.dialogSearch().getDialog().Show(); |
Метод dialog.dialogSearch().getDialog().Show(); отвечает за показ окна. Я его здесь вызвал при отработке скрипта, но его можно обернуть в какой-нибудь onClick и вызывать в нем. Это уже люди сами разберутся, где и как юзать.
Для отслеживания выбора элементов повесимся на событие, которое мы указали в объекте.
BX.addCustomEvent(dialog.getEvent(), (dataEvent) => {
console.info(dataEvent); // данные о выбранном элементе.
dialog.getDialog().Close(); // закроем окно
}); |
Если же нам надо выбрать вообще любой ИБ, то нужно кастомизировать компонент. Благо он сделан с использованием class.php.
Копируем компонент bitrix:catalog.product.search в свое пространство.
Пересоздаем class.php, вызываем в нем подключение родительского класса.
<?php
/** @var \CBitrixComponent $this */
/** @var array $arParams */
/** @var array $arResult */
/** @var string $componentPath */
/** @var string $componentName */
/** @var string $componentTemplate */
/** @var \CBitrixComponent $component */
/** @global \CUser $USER */
/** @global \CMain $APPLICATION */
use Bitrix\Main\Loader;
use Bitrix\Iblock;
Loader::includeModule('iblock');
CBitrixComponent::includeComponentClass('bitrix:catalog.product.search');
class AdminElementSearchComponent extends ProductSearchComponent
{
protected function checkIblockAccess()
{
return true; // это чтоб не проверять, что у нас только каталоги и разрешать все ИБ
}
protected function getIblockList()
{
if ($this->iblockList === null){
$oResult = Iblock\IblockTable::getList([
'filter' => ['=ACTIVE' => 'Y'],
'sel ect' => ['*'],
]);
while ($row = $oResult->fetch()) {
$this->iblockList[$row['ID']] = $row;
}
}
return $this->iblockList;
}
protected function getIblockId()
{
return $this->arParams['IBLOCK_ID'];
}
} |
checkIblockAccess() - чтоб не проверять, что у нас только каталоги и разрешать все ИБ.
getIblockList() - скажет компоненту, какие ИБ можно выбирать в окошке. Собственно, тут же можно сформировать свой список, если задача того требует.
getIblockId() - чтобы тоже избежать проверок на принадлежность ИБ к каталогу, и показывать ИБ из $_GET в изначальной отрисовке окна. Грубо говоря, чтоб в arParams['IBLOCK_ID'] попал ИБ, который мы в js засунули.
Далее, в админке, на своей странице меняем вызов компонента на свой. И в конструктор объекта можно передавать новый урл.
const dialog = new ElementSearch({
IBLOCK_ID: 147,
url: '/bitrix/admin/new_search_element.php'
});
|
import ElementSearch fr om './ElementSearch';
BX(function(){
const dialog = new ElementSearch({
IBLOCK_ID: 147,
url: '/bitrix/admin/new_search_element.php'
});
dialog.dialogSearch().getDialog().Show();
})
|