Самодельная форма добавления элемента на API Битрикс

Просмотров: 52855

Компонент iblock.element.add.form написан таким образом, что вы не сможете (не попотев изрядно и не используя js) как угодно переставлять поля ввода. Например сделать заполненеие текста анонса до ввода разделов. Или переставить чекбоксы свойств до ввода названия (хотя это глупо, но вы не сможжете сделать такую глупость даже если захотите)

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

В большинстве случаев, достаточно воcпользоваться стандартным компонентом iblock.element.add.form. Однако, данный компонент очень давно не обновляется. Назвать его гибким и тонко настраеваемым ни как нельзя. Достаточно часто, для создания формы приходиться писать свои костыли. Например: форму добавления элемента инфоблока через API Битрикс

Компонент iblock.element.add.form написан таким образом, что вы не сможете (не попотев изрядно и не используя js) как угодно переставлять поля ввода. Например сделать заполненеие текста анонса до ввода разделов. Или переставить чекбоксы свойств до ввода названия (хотя это глупо, но вы не сможете сделать такую глупость даже если захотите)

Расскажу как сделать форму через API. Абсолютным костылем данный способ не назвать, в любом случае задача будет решена. И у вас будет возможность оформлять форму как угодно.

Работать будем с методом CIBlockElement::Add - добавляет новый элемент информационного блока. Перед добавлением элемента вызываются обработчики события OnBeforeIBlockElementAdd, из которых можно изменить значения полей или отменить добавление элемента вернув сообщение об ошибке.

Создаем форму на произвольной странице сайта или в основном шаблоне

Для начала: имеем инфоблок "Тест", у которого созданы свойства "Строка", "Список", "Чекбокс", "Файл", "Привязка к разделам". ID этого инфоблока 12

Кстати: в стандартном компоненте не хватает некоторых свойств, например он не умеет выводить свойство привязка к раздел. Как это реализовать можете подсмотреть тут

Далее: Создаем в корне сайта страницу add_form_page.php с таким содержимым

<?
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/header.php");
    //Подключаем модуль инфоблоков
   CModule::IncludeModule('iblock');
   $IBLOCK_ID = 12; //ИД инфоблока с которым работаем
?>

<form name="add_my_ankete" action="/add_form_result.php" method="POST" enctype="multipart/form-data">

Название
<input type="text" name="name" maxlength="255" value="">

Картинка анонса
<input type="file" size="30" name="image" value="">

Свойство Строка
<input type="text" name="line" maxlength="255" value="">

Выпадающий список не множественный
 <select name='selector'>
	<option value='#'>Выберите из списка</option>
	<option value="60">1</option>
	<option value="61">2</option>
</select>
	              
Текст анонса
<textarea name="description" placeholder="Заполните поле"></textarea>
	                
Выбор раздела- множественный
<select name='section_id[]' multiple>
	     <option value='#'>Выберите из списка или начните вводить название</option>
	     <?
	       $arFilter = array('IBLOCK_ID' => $IBLOCK_ID, 'ACTIVE' => 'Y', "DEPTH_LEVEL" => "2");
	       $arSelect = array('ID', 'NAME');
	       $rsSection = CIBlockSection::GetTreeList($arFilter, $arSelect);
	       while ($arSection = $rsSection->Fetch()) {
	     ?>
	       <option value="<?= $arSection['ID']; ?>"><?= $arSection['NAME']; ?></option>
	     <?}?>
</select>
	             
Чекбокс
<label><input type="checkbox" name="chek_box" value="47"> Рассрочка </label>
	               
Произвольный файл
<input type="file" size="30" name="file_pol" value="">
	                    
Привязка к подразделам конкретного раздела другого мнфоблока чекбоксы                 
<?
	   $rsParentSection = CIBlockSection::GetByID(5741);
	   if ($arParentSection = $rsParentSection->GetNext()) {
	   $arFilter = array('IBLOCK_ID' => $arParentSection['IBLOCK_ID'], '>LEFT_MARGIN' => $arParentSection['LEFT_MARGIN'], '<RIGHT_MARGIN' => $arParentSection['RIGHT_MARGIN'], '>DEPTH_LEVEL' => $arParentSection['DEPTH_LEVEL']);
	   $rsSect = CIBlockSection::GetList(array('left_margin' => 'asc'), $arFilter);
	   while ($arSect = $rsSect->GetNext()) {
	   ?>
	    <label><input name='service_dop[]' type="checkbox" value="<?= $arSect['ID']; ?>"> <?= $arSect['NAME']; ?></label>
	   <?}}?>            
	   <input type="submit" value="Отправить">
	 </form>    
<?require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/footer.php"); ?>

Это наша форма, которую заполняет пользователь

Рядом создаем файл add_form_result.php, которому будет передаваться POST запрос и пользователю будет выдаваться сообщение о результате добавления. Содержимое файла:

<?
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/header.php");
define("NO_KEEP_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS", true);
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");
?>
 
<?
if (!empty($_REQUEST['name']) and !empty($_REQUEST['description'])) {
    CModule::IncludeModule('iblock');

    echo 'Вот такие данные мы передали';
    echo '<pre>';
    print_r($_POST);
    echo '<pre>';

    //Погнали
    $el = new CIBlockElement;
    $iblock_id = 24;
    $section_id = false;
    $section_id[$i] = $_POST['section_id']; //Разделы для добавления

    //Свойства
    $PROP = array();

    $PROP['LINE'] = $_POST['line']; //Свойство Строка
    $PROP['SELECTOR'] = $_POST['selector']; //Свойство список
    $PROP['CHEK_BOX'] = $_POST['chek_box']; //Свойство чекбокс
    $PROP['FILE_POL'] = $_FILES['file_pol']; //Свойство файл
    $PROP['SECTIONS_SV'][$c] = $_POST['sections_sv']; //Чекбоксы привязка к разделам

    //Основные поля элемента
    $fields = array(
        "DATE_CREATE" =& gt;
    date("d.m.Y H:i:s"), //Передаем дата создания
	     "CREATED_BY" =& gt; $GLOBALS['USER'] ->GetID(),  //Передаем ID пользователя кто добавляет
	     "IBLOCK_SECTION" =& gt; $section_id[$i], //ID разделов
	     "IBLOCK_ID" =& gt; $iblock_id, //ID информационного блока он 24-ый
	     "PROPERTY_VALUES" =& gt; $PROP, // Передаем массив значении для свойств
	     "NAME" =& gt; strip_tags($_REQUEST['name']),
	     "ACTIVE" =& gt; "Y", //поумолчанию делаем активным или ставим N для отключении поумолчанию
	     "PREVIEW_TEXT" =& gt; strip_tags($_REQUEST['description']), //Анонс
	     "PREVIEW_PICTURE" =& gt; $_FILES['image'], //изображение для анонса
	     "DETAIL_TEXT" =& gt; strip_tags($_REQUEST['description_detail'],
        "DETAIL_PICTURE" =& gt; $_FILES['image_detail'] //изображение для детальной страницы
	   );
	  
	   //Результат в конце отработки
	   if ($ID = $el ->Add($fields)) {
        echo "Сохранено";
    } else {
        echo 'Произошел как-то косяк Попробуйте еще разок';
    }
}
?>
<? require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/footer.php"); ?>

Вот и все. Результат будет отдаваться в запись элемента инфоблока. Уже по вкусу, можете оформлять как угодно, прикручивать js проверку на заполненность или на проверку данных- маски.

На базе данной заметки сделал компонент. Устроен максимально просто, поддается доработкам и расширению функционала. Компонент добавления элемента в инфоблок

Видео: Форма добавления через API

Опубликовав и прочитав записку, понял, что она не до конца понятна. Решил записать поясняющее видео

Обновленное видео, как сделать компонент на базе этой заметки

Спустя какое-то время после написании заметки, сделан видеокурс по созданию доски объявлений. В течении трех серий видеокурса, рассматриваю как сделать компонент на базе способов и методов описанных в заметке.

Кроме того, рассмотрен вариант использования D7 методов. Сам компонент используется и для добавления элемента инфоблока и для редактирования.

Загрузка множественного свойства типа файл

Создаем массив со свойствами файлов, методом CFile::MakeFileArray и передаем в $PROP["MORE_PHOTO"] (в моем случае, свойство с доп картинками)

$arMorePhoto["VALUE"];
    $i = 0;
    foreach ($_POST["MORE_PHOTO"] as $morePhoto) {
        $arMorePhoto['n'.$i] = array("VALUE"=>CFile::MakeFileArray($morePhoto));
        $i++;
    }
$PROP["MORE_PHOTO"] = $arMorePhoto;
Arsen Sheremeta 30.09.2020
Цитата
Михаил Базаров пишет:
[QUOTE][URL=/club/user/14020/]Arsen Sheremeta[/URL] пишет:
Здравствуйте.
У меня пошаговая форма на 6 шагов. Подскажите пожалуйста как сделать чтоб после первого шага форма  создавала запись (элемент), а с каждым следующим шагом, обновляла туже запись а не создавала новую? Спасибо![/QUOTE] На первом шаге создаете элемент методом: CIBlockElement::Add
На остальных обновляете методом: CIBlockElement::Update
Спасибо!
Roma Rampagev 03.10.2020
Все сделал
Максим Максимов 16.03.2021
Добрый день
Спасибо за базу знаний по битрикс !
А есть ли возможность сделать и вашей формы редактор статей на сайте ?

Не только создавать статью но и изменять её?
Михаил Базаров 20.03.2021
Цитата
Максим Максимов написал:
Добрый день
Спасибо за базу знаний по битрикс !
А есть ли возможность сделать и вашей формы редактор статей на сайте ?

Не только создавать статью но и изменять её?
В целом да. Нужно передать сюда ID статьи и по нему получить все содержимое элемента (методом CIBlockElement::GetByID)
Заполнить им все поля, а дальше в обработчике обновлять с помощью $el->Update
Владимир 25.06.2021
Здравствуйте!
Хорошее видео. Не подскажете как это всё отправить на почту?
Столкнулся с проблемой нет нигде описание как добавить в форму обратной связи поле "select", решил попробовать как у вас на видео, но не понятно как оправлять ее на почту... ну и прикрутить recaptcha.
Спасибо!
Антон 02.06.2023
Добрый!
Как это все обернут в popUp окно после отправки данных?

    //Результат в конце отработки   if ($ID = $el->Add($fields)) {     echo "Сохранено";   } else {     echo 'Произошел как-то косяк Попробуйте еще разок';   } }

все сделал все работает прекрасно но не красиво нужно всплывающие окно https://bazarow.ru/blog-note/2449/
Михаил Базаров 02.06.2023
Цитата
Антон написал:
Добрый!
Как это все обернут в popUp окно после отправки данных?
//Результат в конце отработки   if ($ID = $el->Add($fields)) {     echo "Сохранено";   } else {     echo 'Произошел как-то косяк Попробуйте еще разок';   } }
все сделал все работает прекрасно но не красиво нужно всплывающие окно https://bazarow.ru/blog-note/2449/

Вариантов много, но самый простой:
- В параметры компонента передать параметр "AJAX_MODE"=>"Y", в компонент не надо ни чего добавлять- там само сработает.
- Саму форму взять в скрытый div, спозицианированный во всплывающее окно.
- При клике на нужную кнопку или ссылку, добавлять этому div-у класс включающий его в показ.
И все сработает.

Более сложный вариант, вот так текстом не расскажу, могу только наводку дать.
Размещаете форму на некой странице и подгружаете ее (форму) в ajax popap. Что бы не мучаться с оконной библиотекой битрикса, можно воспользоваться fancybox - там есть метод работы с подгрузкой сраниц во всплывающее окно.
Гость 04.12.2023
Михаил, такой вопрос. Когда мы отдаем данные в метод add ($el->Add($fields)), Битрикс в фоне сам их санитайзит? Предварительная обработка не требуется, когда мы формируем массив свойств, полученных из POST?
Дмитрий 05.05.2024
Спасибо за видео, как раз то, что нужно. Только такой вопрос, можно ли таким способом сделать компонент? Чтобы форма и результат хранились в нем, а не в корне самого сайта. И добавлять его на нужную страницу
Михаил Базаров 05.05.2024
Цитата
Дмитрий написал:
Спасибо за видео, как раз то, что нужно. Только такой вопрос, можно ли таким способом сделать компонент? Чтобы форма и результат хранились в нем, а не в корне самого сайта. И добавлять его на нужную страницу
Вот тут, на протяжении 3-х серий рассказываю как это все завернуть в собственный компоненте. Там, как раз эту заметку и беру за основу
https://bazarow.ru/video/video_new/seazon_2_2024/add_edit_form_2/