Создание и удаление полей в форме кликом по кнопке (jquery)

В данной статье рассматривается процесс создания формы с полями, которые можно добавлять (и удалять) по клику на соответствующие кнопки. Также рассмотрен процесс обработки значений данных полей на сервере.

Не так давно автору настоящей статьи пришлось разрабатывать форму, в которой бы пользователь мог бы добавлять дополнительное шаблонное поле (и удалять его по своему желанию). Само собой, что на стороне сервера всё эти данные должны были обрабатываться и, после обработки, отправляться на почту администратору сайта. К слову, данный сайт был на битриксе, но форма при этом была сделана универсальная. Единственное, что письмо отправлялось через почтовый шаблон битрикса, но об этом в самом конце.  Конечно, автор признает, что предложенное решение не единственное и, вероятно, не лучшее. Но оно рабочее, а также достаточно простое в реализации и переносе на другие проекты.

Статья поделена на три небольших шага:

  1. HTML-шаблон формы
  2. Обработка на стороне клиента
  3. Обработка на стороне сервера и отправка на почту

Шаг 1. HTML-шаблон формы

Начать следует с хтмл-шаблона формы. В целом, с поправкой на верстку того сайта, он стандартный. Наибольший интерес представляет поле «Добавить деталь» — т.к. это первое поле из «динамических» полей, т.е. тех, которые пользователь сможет добавить.

Также обратите внимание на поля «Марка» и «Модель» — их содержимое автозаполняется из GET-параметров адресной строки, т.к. переход происходит со страницы, где известны переменные марки и модели автомобиля.

Собственно, шаблон формы:

<div class="col-md-offset-2 col-md-8" style="margin: auto; width: 45%; ">
<form class=" form-horizontal content-dialog" id="call_form" class="uk-form" >

<div class="col-sm-12 col-xs-12 col-md-4">
<div class="form-group">
<label class="col-sm-12" for="name">
Имя</label>
<div class="col-sm-12">
<input class="input-sm form-control" type="text" id="name" name="name" value=""  label="Имя" placeholder="Например: Иван">
</div>
</div>
</div>
<div class="col-sm-12 col-xs-12 col-md-4">
<div class="form-group">
<label class="col-sm-12" for="phone">
Телефон<span style="color:#a94442;">
*&nbsp;</span>
</label>
<div class="col-sm-12">
<div class="">
<input class="input-sm form-control" type="tel" id="phone" name="phone" value="" placeholder="+7 (999) 999-99-99" label="Телефон">
</div>
</div>
</div>
</div>
<div class="col-sm-12 col-xs-12 col-md-4">
<div class="form-group">
<label class="col-sm-12" for="email">
Email</label>
<div class="col-sm-12">
<input class="input-sm form-control" type="text" id="email" name="email" value=""  placeholder="as-parts@as-parts.ru" label="Email">
</div>
</div>
</div>
<div class="col-sm-12 col-xs-12 col-md-4">
<div class="form-group">
<label class="col-sm-12" for="vin">
VIN<span style="color:#a94442;">
*&nbsp;</span>
</label>
<div class="col-sm-12">
<input class="input-sm form-control" type="text" id="vin" name="vin" value="" placeholder="JTHBF5D2405041961" label="VIN">
</div>
</div>
</div>
<div class="col-sm-12 col-xs-12 col-md-4">
<div class="form-group">
<label class="col-sm-12" for="car_firm">
Марка<span style="color:#a94442;">
*&nbsp;</span>
</label>
<div class="col-sm-12">
<input class="input-sm form-control" type="text" id="car_firm" name="car_firm" value="<?echo $_GET['f']; ?>" label="Марка" placeholder="Например: LEXUS" >
</div>
</div>
</div>
<div class="col-sm-12 col-xs-12 col-md-4">
<div class="form-group">
<label class="col-sm-12" for="car_model">
Модель</label>
<div class="col-sm-12">
<input class="input-sm form-control" type="text" id="car_model" name="car_model" value="<?echo $_GET['mname']; ?>"  label="Модель" placeholder="Например: IS250">
</div>
</div>
</div>



<div class="add_details_form">
<div  id="form_add_details_uuidtmpl" class="detailsForm">
	<div class="col-sm-10 add " id="add1">
		<label class="col-sm-12" for="detail">
			Деталь<span style="color:#a94442;">
			*&nbsp;</span>
		</label>
		<input class="input-sm form-control" type="text" id="val" name="val[]" value=""  placeholder="Деталь: например капот" label="Деталь">

	</div>



</div>
<div onclick="addField();"  class="btn pull-right btn-success" style="padding: 5px; margin: 5px 0px; border-radius: 5px;">Добавить деталь</div>

</div>
<br>


<div class="col-sm-12 col-xs-12">
<div class="form-group">
<label class="col-sm-12" for="">
Комментарий</label>
<div class="col-sm-12">
<textarea class="input-sm form-control" type="text" id="comment" name="comment" placeholder="" rows="3">
</textarea>

</div>
</div>
</div>
<div class="col-md-12">
<button class="btn pull-right btn-success" type="submit">
Отправить</button>
</div>
</form>

</div>

Особый интерес, как было сказано выше, представляет вот этот блок:

<div class="add_details_form">
<div  id="form_add_details_uuidtmpl" class="detailsForm">
	<div class="col-sm-10 add " id="add1">
		<label class="col-sm-12" for="detail">
			Деталь<span style="color:#a94442;">
			*&nbsp;</span>
		</label>
		<input class="input-sm form-control" type="text" id="val" name="val[]" value=""  placeholder="Деталь: например капот" label="Деталь">

	</div>



</div>
<div onclick="addField();"  class="btn pull-right btn-success" style="padding: 5px; margin: 5px 0px; border-radius: 5px;">Добавить деталь</div>

</div>
<br>

Параметр onclick=»addField();»  у кнопки «Добавить деталь» — это функция, что добавляет дополнительное поле «добавить деталь». Сама функция будет объявлена на следующем шаге, дабы не смешивать html и js.

Также обратите внимание, т.к. это, пожалуй, ключевой момент в данном алгоритме — у input’а детали name=»val[]». Что это значит? Это позволяет поместить значения из полей с таким именем при отправке на сервер в массив $_POST[‘val’]. Т.е. таких полей может быть много.

Шаг 2. Обработка на стороне клиента

Здесь особых новшеств также нет. Всё достаточно стандартно, но некоторые моменты требуют уточнения.

Весь js для данной формы (в том числе и функции добавления/удаления полей):

<script type="text/javascript">
//Функция добавления поля 
function addField () {
  
  var telnum = parseInt($("#form_add_details_uuidtmpl").find("div.add:last").attr("id").slice(3))+1;
  $("div#form_add_details_uuidtmpl").append('<div id="add'+telnum+'" class="col-sm-10  add"><input type="text" placeholder="Деталь: например капот" name="val[]" id="val"  value="" style="width: 90%; display: inline"/><span title="удалить поле" class="fa fa-remove" onclick="deleteField('+telnum+');" style=" float: right;color: #333; background-color: #d4d4d4; border-color: #8c8c8c; padding: 5px 10px; font-size: 16px; line-height: 1.5; border-radius: 3px;"></span></div>');
}
//Функция удаления поля
function deleteField (id) {
	$('div#add'+id).remove();
	writeFieldsVlues();
}


$('#call_form').submit(function(e){

	e.preventDefault();
	$.ajax({
	url: "./mail.php",
	type: "POST",
	data: $('#call_form').serialize(),
	success: function(response) {
	//обработка успешной отправки
	  alert("Заявка отправлена!");

	},
	error: function(response) {
	//обработка ошибок при отправке
	}
	});
	});


</script>

Функции addField и deleteField, наверное не нуждаются в особом комментарии. Первая функция создает новое поле «добавить деталь» с уникальным айдишником, сразу после предыдущего поля и кнопку «удалить поле». Как видно выше, весь html кнопки вписан в append().

Функция deleteField, в свою очередь, принимает в качестве аргумента id и удаляет связанный с ним input.

Ну а $(‘#call_form’).submit(function(e) отправляет ajax’ом (без перезагрузки страницы) данные на сервер. Тут всё стандартно.

Шаг 3. Обработка на стороне сервера и отправка на почту

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

<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");

    $fname = $_POST['name'];
    $ftelep = $_POST['phone'];
    $fmail =  $_POST['email'];
    $fvin =  $_POST['vin'];
    $fmark =  $_POST['car_firm'];
    $fmodel =  $_POST['car_model'];
    $fdetail = implode(" | ",$_POST["val"]);
    $fcomment =  $_POST['comment'];




            $message .= " 
			<tr style=\"background-color: #f8f8f8;\">
			<td style='padding: 10px; border: #e9e9e9 1px solid;'><b>Имя</b></td>
			<td style='padding: 10px; border: #e9e9e9 1px solid;'>$fname</td>
		    </tr>
			
			<tr style=\"background-color: #f8f8f8;\">
			<td style='padding: 10px; border: #e9e9e9 1px solid;'><b>Телефон</b></td>
			<td style='padding: 10px; border: #e9e9e9 1px solid;'>$ftelep</td>
		    </tr>
			
			<tr style=\"background-color: #f8f8f8;\">
			<td style='padding: 10px; border: #e9e9e9 1px solid;'><b>Email</b></td>
			<td style='padding: 10px; border: #e9e9e9 1px solid;'>$fmail</td>
		    </tr>
			
			
			<tr style=\"background-color: #f8f8f8;\">
			<td style='padding: 10px; border: #e9e9e9 1px solid;'><b>VIN</b></td>
			<td style='padding: 10px; border: #e9e9e9 1px solid;'>$fvin</td>
		    </tr>
			
			<tr style=\"background-color: #f8f8f8;\">
			<td style='padding: 10px; border: #e9e9e9 1px solid;'><b>Марка</b></td>
			<td style='padding: 10px; border: #e9e9e9 1px solid;'>$fmark</td>
		    </tr>
			
			
			<tr style=\"background-color: #f8f8f8;\">
			<td style='padding: 10px; border: #e9e9e9 1px solid;'><b>Модель</b></td>
			<td style='padding: 10px; border: #e9e9e9 1px solid;'>$fmodel</td>
		    </tr>
			

			<tr style=\"background-color: #f8f8f8;\">
<td style='padding: 10px; border: #e9e9e9 1px solid;'><b>Детали</b></td>
			<td style='padding: 10px; border: #e9e9e9 1px solid;'>$fdetail</td>
		    </tr>
			
			<tr style=\"background-color: #f8f8f8;\">
			<td style='padding: 10px; border: #e9e9e9 1px solid;'><b>Комментарий</b></td>
			<td style='padding: 10px; border: #e9e9e9 1px solid;'>$fcomment</td>
		    </tr>
			
			";


$message = "<table style='width: 100%;'>$message</table>";

$arr['MESSAGE'] = $message;
file_put_contents('testform.txt', $message);
CEvent::Send('VIN', SITE_ID, $arr, "N", "63", array($_FILES['Фотография']['tmp_name']));

Итак, шаг первый, обработка данных:

    $fname = $_POST['name'];
    $ftelep = $_POST['phone'];
    $fmail =  $_POST['email'];
    $fvin =  $_POST['vin'];
    $fmark =  $_POST['car_firm'];
    $fmodel =  $_POST['car_model'];
    $fdetail = implode(" | ",$_POST["val"]);
    $fcomment =  $_POST['comment'];

Мы приняли данные из формы. Обратите внимание, что массив $_POST[«val»] мы «склеили» через разделитель |, т.е. данные из каждого динамического поля «добавить деталь» будут отделяться от предыдущего таким символом. Разделитель, само собой, может быть любым.

Далее мы верстаем таблицу из значений, полученных с формы. Обратите внимание, что предложенном примере все данные, вместе с версткой «склеены» в одну переменную $message. В данном случае — это оправданный шаг.

Склеив всё в одну переменную, мы можем отправить данные на почту админу:

$arr['MESSAGE'] = $message;
file_put_contents('testform.txt', $message);
CEvent::Send('VIN', SITE_ID, $arr, "N", "63", array($_FILES['Фотография']['tmp_name']));

За отправку отвечает функция CEvent::Send, в которой первое значение — это символьный код типа почтового шаблона, а 63 — это id необходимого почтового шаблона. file_put_contents — это «страховка» для контроля отправки данных. После отладки эту строчку можно удалить.

В целом, это всё. Проделав эти три шага, вы получите рабочую форму с динамическими полями, которую можно использовать на любом сайте, который работает на php (Битриксовую функцию отправки на почту можно заменить на mail(); ).