Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Добавление и удаление input (https://javascript.ru/forum/misc/71282-dobavlenie-i-udalenie-input.html)

skitskis 07.11.2017 12:21

Добавление и удаление input
 
Добрый день!
Работаю с php и к сожалению не владею знаниями программирования на jquery.
Задача состоит в том что надо добавлять и удалять блоки с input и считать их количество, добавление проходит нормально, подсчет идет верный, но вот при удалении считает неверно.
Например, добавил 5 блоков, он посчитал их верно, показал цифру 5, нажал удалить один, стало 4 но цифру все ровно показывает 5, удалил еще один, стало 3, цифру показывает 5.

Html:
<!--------- Строка начало --------->
        <div class="field">
            <div class="col_left">
                <div class="border">
                    <input type="text" name="tag_1" value="" placeholder="TEG" />
                </div>
            </div>
            <div class="col_centr">
                <div class="border">
                    <input type="text" name="tag_name_1" value="" placeholder="Название поля" />
                </div>
            </div>
            <div class="col_right">
                <div class="border">
                    <select type="radio" name="tag_template_1">
                        <option value="0">Текстовое</option>
                        <option value="1">Числовое с переводом числа в текст</option>
                        <option value="2">Срок исполнения</option>
                    </select>
                </div>
            </div>
            <div class="clear"></div>
        </div>
        <!--------- Строка конец --------->
        <div class="inputs">
    
        </div>
        <input id="last_numer" name="" value="1">


Script:
<script>

    
$(document).ready(function(){


	var i = 2;
	
	$('#add').click(function() {
            $('\n\
    \n\
<!--------- Строка начало --------->\n\
        <div class="field">\n\
            <div class="col_left">\n\
                <div class="border">\n\
                    <input type="text" name="tag_' + i + '" value="" placeholder="TEG" />\n\
                </div>\n\
            </div>\n\
            <div class="col_centr">\n\
                <div class="border">\n\
                    <input type="text" name="tag_name_' + i + '" value="" placeholder="Название поля" />\n\
                </div>\n\
            </div>\n\
            <div class="col_right">\n\
                <div class="border">\n\
                    <select type="radio" name="tag_template_' + i + '">\n\
                        <option value="0">Текстовое</option>\n\
                        <option value="1">Числовое с переводом числа в текст</option>\n\
                        <option value="2">Срок исполнения</option>\n\
                    </select>\n\
                </div>\n\
            </div>\n\
            <div class="clear"></div>\n\
        </div>\n\
        <!--------- Строка конец --------->\n\
\n\
').fadeIn('slow').appendTo('.inputs');
                document.getElementById('last_numer').value = i;
		i++;
	});
	
	$('#remove').click(function() {
            $('.field:last').remove();
            i--;
            document.getElementById('last_numer').value = i;
            
	});
	

// here's our click function for when the forms submitted
	
	$('.submit').click(function(){
								
	
	var answers = [];
    $.each($('.field'), function() {
        answers.push($(this).val()); 
    });
	
    if(answers.length == 0) { 
        answers = "none"; 
    }   

	alert(answers);
	
	return false;
								
	});

    

});

</script>

laimas 07.11.2017 12:27

skitskis,
нужно добавлять клонированный <div class="field"> со всем его содержимым. И именование полей мягко сказать не очень. Это затем отправляется на сервер ведь?

Вставлять в html код \n бессмысленно.

рони 07.11.2017 12:27

skitskis,
где кнопки добавить и удалить?

skitskis 07.11.2017 12:30

Цитата:

Сообщение от рони (Сообщение 469433)
skitskis,
где кнопки добавить и удалить?

ой, да.
<!--------- Строка начало --------->
        <div class="form_group">
            <div class="col_left">
            <a href="#" id="add">Добавить</a> | <a href="#" id="remove">Удалить</a> 
            <div class="clear"></div>
        </div>
        <!--------- Строка конец --------->

рони 07.11.2017 12:33

skitskis,
строки 38 и 39 поменять местами и строка 7 var i = 1;

рони 07.11.2017 12:36

Цитата:

Сообщение от skitskis
ой, да.

тогда ещё в оба клика добавить .click(function(event) {
event.preventDefault();

laimas 07.11.2017 12:36

рони,
не надо ничего менять, это нужно выбрасывать, так как и для именования полей это вредно, и для подсчета не нужно, достаточно посчитать элементы ".field", если надо.

skitskis 07.11.2017 12:37

Цитата:

Сообщение от laimas (Сообщение 469432)
skitskis,
нужно добавлять клонированный <div class="field"> со всем его содержимым. И именование полей мягко сказать не очень. Это затем отправляется на сервер ведь?

Вставлять в html код \n бессмысленно.


так у меня и добавляется <div class="field"> и все содержимое, или я что то не понял. Да, потом отправляю на сервер.

laimas 07.11.2017 12:42

Цитата:

Сообщение от skitskis
так у меня и добавляется <div class="field"> и все содержимое, или я что то не понял.

Не надо ничего добавляемого описывать:

$('div.field').first().clone()....


То есть взять первый набор (который нельзя удалить, нет у него кнопок, а еще лучше невидимы, они тоже клонируются), очищаются его поля и сбрасывается список. Имена полей при этом никакой нумерации не имеют, это как раз будет геморрой для РНР, вот так надо:

tag[], tag_nam[], ....

И получите массив в $_POST.

skitskis 07.11.2017 12:43

Цитата:

Сообщение от laimas (Сообщение 469437)
рони,
не надо ничего менять, это нужно выбрасывать, так как и для именования полей это вредно, и для подсчета не нужно, достаточно посчитать элементы ".field", если надо.

да, можно и посчитать элементы ".field", мне просто нужно понимать количество полей, я потом буду пробегать циклом for. Но как мне вытащить это значение? просто скрип я не писал, я его кусками собрал из интернета...

рони 07.11.2017 12:44

Цитата:

Сообщение от laimas
это нужно выбрасывать,

ок! ниже код исправляющий подсчёт, но лучше конечно прислушаться к laimas, и имена полей изменить

<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
 <script>


$(document).ready(function(){


  var i = 1;

  $('#add').click(function(event) {event.preventDefault();
            $('\n\
    \n\
<!--------- Строка начало --------->\n\
        <div class="field">\n\
            <div class="col_left">\n\
                <div class="border">\n\
                    <input type="text" name="tag_' + i + '" value="" placeholder="TEG" />\n\
                </div>\n\
            </div>\n\
            <div class="col_centr">\n\
                <div class="border">\n\
                    <input type="text" name="tag_name_' + i + '" value="" placeholder="Название поля" />\n\
                </div>\n\
            </div>\n\
            <div class="col_right">\n\
                <div class="border">\n\
                    <select type="radio" name="tag_template_' + i + '">\n\
                        <option value="0">Текстовое</option>\n\
                        <option value="1">Числовое с переводом числа в текст</option>\n\
                        <option value="2">Срок исполнения</option>\n\
                    </select>\n\
                </div>\n\
            </div>\n\
            <div class="clear"></div>\n\
        </div>\n\
        <!--------- Строка конец --------->\n\
\n\
').fadeIn('slow').appendTo('.inputs');
                i++;
                document.getElementById('last_numer').value = i;

  });

  $('#remove').click(function(event) {
            if(i == 1) return;
            event.preventDefault();
            $('.field:last').remove();
            i--;
            document.getElementById('last_numer').value = i;

  });


// here's our click function for when the forms submitted

  $('.submit').click(function(){


  var answers = [];
    $.each($('.field'), function() {
        answers.push($(this).val());
    });

    if(answers.length == 0) {
        answers = "none";
    }

  alert(answers);

  return false;

  });



});

</script>

</head>

<body>
<!--------- Строка начало --------->
        <div class="field">
            <div class="col_left">
                <div class="border">
                    <input type="text" name="tag_1" value="" placeholder="TEG" />
                </div>
            </div>
            <div class="col_centr">
                <div class="border">
                    <input type="text" name="tag_name_1" value="" placeholder="Название поля" />
                </div>
            </div>
            <div class="col_right">
                <div class="border">
                    <select type="radio" name="tag_template_1">
                        <option value="0">Текстовое</option>
                        <option value="1">Числовое с переводом числа в текст</option>
                        <option value="2">Срок исполнения</option>
                    </select>
                </div>
            </div>
            <div class="clear"></div>
        </div>
        <!--------- Строка конец --------->
        <div class="inputs">

        </div>
        <input id="last_numer" name="" value="1">
    <!--------- Строка начало --------->
        <div class="form_group">
            <div class="col_left">
            <a href="#" id="add">Добавить</a> | <a href="#" id="remove">Удалить</a>
            <div class="clear"></div>
        </div>
        </div>
        <!--------- Строка конец --------->

    </body>
</html>

skitskis 07.11.2017 12:46

Цитата:

Сообщение от laimas (Сообщение 469439)
вот так надо:

tag[], tag_nam[], ....

И получите массив в $_POST.

спасибо, попробую так.

рони 07.11.2017 12:49

skitskis,
$("[name='tag[]']").each()

но наверно будет достаточно $(".field").serialize()

laimas 07.11.2017 12:50

skitskis,
еще раз и последний - именование полей как tag_1, tag_2, ... это бессмыслица ничего кроме геморроя на сервере не дающая, так как требует сканирования ключа. Это и на клиенте геморрой, так как вся эта кухня с расчетом ради этого у вас и крутится.

Начните с именования полей, и просто клонирование, и код будет лаконичней, и мусора в нем будет меньше.

skitskis 07.11.2017 12:52

рони, спасибо!
Работает.
Я так понимаю добавили только это:
.click(function(event) {event.preventDefault()

А почему он считал на прибавление нормально а на минус нет?

skitskis 07.11.2017 12:55

laimas, рони
Спасибо Вам большое.

laimas 07.11.2017 12:57

skitskis,
все таки вы остановились на самом худшем, это значит, что и в РНР у вас не очень продуман код. )

skitskis 07.11.2017 13:02

laimas
неее, я попробую как советовали. tag[], tag_nam[], ....

laimas 07.11.2017 13:16

Цитата:

Сообщение от skitskis
я попробую как советовали

В этом случае "бухгалтерии" на клиенте не нужно, я же вижу что так и осталось - добавление с описанием, нумерацией... Кнопка удалить должна быть у каждого добавляемого блока своя, а Добавить одна общая. И список не может быть типом "radio".

Начинать надо с сервера, он и определит что нужно будет на клиенте.

Nexus 07.11.2017 13:34

Сегодня с утра решал почти такую же задачу.
https://jsfiddle.net/320zmnxw/

laimas 07.11.2017 13:44

Nexus,
ну если для такой, то слишком много. :)

Если по уму и тип должен определять клиент, то:

<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<style>
.field:first-child .del {
    display: none;
}
</style>
<script type="text/javascript">
$(function() {
    $('#add').click(function() {
       $('div.field').first()
                     .clone()
                     .appendTo('form')
                     .find('input,select').val('')
                     .end()
                     .find('a').click(function() {
                        $(this).parent().remove()
                     })     
    });
    $('form').submit(function(e) {
        e.preventDefault();
        //....
    })
});
</script>
</head>
<body>
<form>
<div class="field">
            <div class="col_left">
                <div class="border">
                    <input type="text" name="tag[]" required="" value="" placeholder="TAG" />
                </div>
            </div>
            <div class="col_centr">
                <div class="border">
                    <input type="text" name="tag_name[]" required="" value="" placeholder="Название поля" />
                </div>
            </div>
            <div class="col_right">
                <div class="border">
                    <select required="" name="tag_template[]">
                        <option value="">Выберите</option>
                        <option value="1">Текстовое</option>
                        <option value="2">Числовое с переводом числа в текст</option>
                        <option value="3">Срок исполнения</option>
                    </select>
                </div>
            </div>
            <a class="del">Удалить</a>
            <div class="clear"></div>
        </div>
<button>Send</button>
</form>
<a id="add">Добавить</a>
</body>
</html>

Nexus 07.11.2017 13:52

laimas, я сегодня Вас не понимаю :)
Цитата:

Сообщение от laimas
ну если для такой, то слишком много

Если "слишком много" - про кол-во кода, то в наших реализациях принципиальная разница, отсюда и разница в символах.

laimas 07.11.2017 13:59

Nexus,
именно "количество", автору то всего надо клонировать и добавить. :) А "громоздкость" его кода из-за пагубного представления, что field_name_1, field_name_2, это удобно.

skitskis 07.11.2017 14:27

laimas,
Это то что нужно )))
До этого я не работал с передачей массива через input.
На сервере обрабатываю так:
$count = count($_POST['tag'])-1;
    for($i=0;$i<=$count;$i++) {
            $tag[$i]['tag'] = $_POST['tag'][$i];
            $tag[$i]['tag_name'] = $_POST['tag_name'][$i];
            $tag[$i]['tag_template'] = $_POST['tag_template'][$i];
        
    }

Nexus 07.11.2017 14:38

skitskis, можно так:
for($i=0;$i<count($_POST['tag']);$i++)


<?php
	for($i=0;$i<count($_POST['tag']);$i++){
		$tag[$i]=array();
		foreach(array('tag','tag_name','tag_template') as $key)
			$tag[$i][$key]=isset($_POST[$key][$i])?htmlspecialchars($_POST[$key][$i]):null;
    }

laimas 07.11.2017 14:39

Цитата:

Сообщение от skitskis
На сервере обрабатываю так:
$count = count($_POST['tag'])-1;
for($i=0;$i<=$count;$i++) {

Зачем?

skitskis 07.11.2017 14:53

laimas,
я еще это добавляю в сессию, так как у меня есть еще другие поля, и если они не заполнены, мне нужно потом подставить обратно уже заполненные, ну а после уже добавить в базу данных значения. По другому я не знаю как ))

laimas 07.11.2017 15:05

Цитата:

Сообщение от skitskis
я еще это добавляю в сессию, так как у меня есть еще другие поля, и если они не заполнены, мне нужно потом подставить обратно уже заполненные

И что, это повод для того чтобы "перекладывать" данные из одного места в другое, имеется ввиду из массива $_POST в массив $tag? Что это дает? Ничего полезного, если уж и сохранить в сессии, то достаточно $_SESSION['name'] = $_POST, зачем здесь ненужный цикл?

Я не знаю чего еще не заполнено (единственное что можно предположить, это не знаем ID новой записи, но это иной вопрос), но если добавление данных, это этапы, то значит на каждом из них требуется проверка, которую вы обязаны делать - проверка обязательного заполнения, истинность данных (соответствие каждого из наборов). И таковую проверку просто сделать без явных циклов, для этого в РНР масса функций для работы с массивами.

А коли запись в базу, то гораздо полезнее будет подготовить из наборов полей данные для каждой строки в sql-таблице, в которые они будут вставлены. А делается это опять таки просто:

$data = array_map(null, $_POST['tag'], $_POST['tag_name'], $_POST['tag_template']);


Но после того как данные будут проверены и не будет выявлено ошибок.

skitskis 07.11.2017 15:12

laimas,
я понял, спасибо )

laimas 07.11.2017 15:21

Nexus,
htmlspecialchars - не надо этого, вредное занятие при записи в базу.

skitskis 10.11.2017 15:16

Всем доброго дня!
У меня еще маленький вопрос.

Вывожу данные:
<table class="table_style_1">
    <?php foreach ($tags as $item):?>
    <tr class="field">
        <td width="150px">
            <input type="hidden" name="id[]" value="<?=$item['id']?>" />
            <input disabled="" style="text-transform: uppercase" type="text" name="tag" value="<?=$item['tag']?>" placeholder="TEG" />
        </td>
        <td>
            <input disabled="" type="text" name="tag_name" value="<?=$item['tag_name']?>" placeholder="Название поля" />
        </td>
        <td width="200px">
            <select disabled="" type="radio" name="tag_template">
                <option <?php if($item['tag_template'] == '0') echo 'selected=""';?> value="0">Текстовое</option>
                <option <?php if($item['tag_template'] == '1') echo 'selected=""';?> value="1">Числовое с переводом числа в текст</option>
                <option <?php if($item['tag_template'] == '2') echo 'selected=""';?> value="2">Срок исполнения</option>
            </select>
        </td>
        <td id="open" width="32px">
            <a class="list_button" id="open"><i title="Редактировать" class="fa fa-pencil" aria-hidden="true"></i></a>
        </td>
        <td id="save" width="32px" style="display: none">
            <a class="list_button" id="save" href=""><i title="Сохранить" class="fa fa-save" aria-hidden="true"></i></a>
        </td>
        <td width="32px">
            <a class="list_button" id="del" href=""><i title="Удалить" class="fa fa-trash-o" aria-hidden="true"></i></a>
        </td>
    </tr>
    <?php endforeach;?>
</table>


По умолчанию input disabled="", при нажатии на кнопку open, делаю input открытым и открываю кнопку сохранить.
$("#open").click(function(){
    $(this).parent().first().find('input,select').prop('disabled',false);
    $(this).parent().find('td#open').css({'display': 'none'});
    $(this).parent().find('td#save').css({'display': ''});
});


Но данное условие срабатывает только на первый элемент. ????

Nexus 10.11.2017 15:20

skitskis, ID - уникальный идентификатор.
Именно так нужно в большинстве случаев стоит понимать значение этих двух букв.

Замените атрибут id на class.

skitskis 10.11.2017 15:29

Nexus, спасибо ))) все работает. Теперь буду знать, а то уже два дня сижу...

laimas 10.11.2017 16:10

...
Цитата:

Сообщение от skitskis
foreach ($tags as $item)
name="id[]"
name="tag_name"
name="tag_template"

?

skitskis 12.11.2017 11:43

Цитата:

Сообщение от laimas (Сообщение 469746)
...


?

да, я знаю, просто был недописанный код.
name="id[]"
name="tag_name[]"
name="tag_template[]"
))

laimas 12.11.2017 12:55

Это не все. Если ранее была тема о добавлении данных, то там был массив полей формирующийся динамически. В данном случае похоже речь идет о редактировании, а значит поля формы лучше связывать по id, а не опять набором по порядку, это может привести к ошибкам нежелательным.

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

name="tag_name[<?=$item['id']?>]"
name="tag_template[<?=$item['id']?>]"

и каждый из этих ключей будет содержать массив, ключи у которого есть ID записей из базы. Можно задать имена и так, чтобы был один многомерный массив, каждое вложение которого, это массив, ключи которого ID, а значение ассоциативный массив: tag_name=>значение, tag_template=>значение.

А если бы ваш список содержал с десяток опций так бы и определялся выбор?

if($item['tag_template'] == '2') echo 'selected=""'

skitskis 23.01.2018 18:56

Доброго все вечера!
Почти закончил уже свой проект, но вернулся опять к тому с чего начал и обнаружил что не все работает как хотел.

А именно: есть tr строки для клонирования, в них есть select со значение value шаблона input. Задача при смене значения select.set_tag_template изменить id поля input.tag_template.

делаю я это удалением старого поля и записываю новое поле с новым id.

Дело в том что, первая строка работает и я отлавливаю id, но после клонирования, в следующие строки я уже не могу поймать значение select.

Вот я завернул, надеюсь понятно. Вот сам код:
<form action="" method="POST" enctype="multipart/form-data">  
    <input type="hidden" name="agreement_id" value="<?=$data['id']?>" />
    
    <table class="table_style_1">
    <thead id="sortable" rel="agreement_tags">
    <tr class="field">
        <td width="20px">
            <a class="sortable_a"><i title="Переместить" class="fa fa-sort" aria-hidden="true"></i></a>
        </td>
        <td width="150px">
            <input type="hidden" name="id[]" value="0" />
            <input type="text" style="text-transform: uppercase" name="tag[]" value="" placeholder="TEG" />
        </td>
        <td width="200px">
            <input type="text" name="tag_name[]" value="" placeholder="Название поля" />
        </td>
        <td class="delete_clase_tag_template">
            <input type="text" name="tag_text[]" class="tag_template" value=""/>
        </td>
        <td width="200px">
            <select class="set_tag_template" type="radio" name="tag_template[]">
                <option value="text">Текстовое</option>
                <option value="srok_r_d">Срок рабочие дни</option>
                <option value="adres">Адрес</option>
            </select>
        </td>
        <td width="32px">
            <button name="save_tags" type="submit" class="save"><i title="Сохранить" class="fa fa-save" aria-hidden="true"></i></button>
        </td>
        <td width="32px" class="td_del_button">
            <a class="list_button_del" id="del"><i title="Удалить" class="fa fa-trash-o" aria-hidden="true"></i></a>
        </td>
    </tr>
    </thead>
    <tbody class="inputs_tag">
    
    </tbody>
    <tfoot>
    <tr class="tr_hiden_add_produkt_score">
        <td colspan="7">
            <a class="add_tag">Добавить тег</a>
        </td>
    </tr>
</table>
</form>


<script>
$(function() {
    $('.add_tag').click(function() {
       $('.field').first()                     
                     .clone()                      
                     .appendTo('.inputs_tag')              
                     .end()
                     .find('input,select').val('').end()                     
                     .find('input.id').val('0').end()
                     .find('.list_button_del').remove().end()
                     .find('.td_del_button').append('<a class="list_button_del" id="del"><i title="Удалить" class="fa fa-trash-o" aria-hidden="true"></i></a>')
                     .end()                     
                     .find('.list_button_del#del').click(function() {
                        $(this).parent().parent().remove();
                     })
    });
});
$(function() {
    $('.list_button_del#del').click(function() {
            $(this).parent().parent().remove();
    });
});   
    
    
    
//смена полей ввода (тег поля)//
$(function() {
    $('.set_tag_template').change(function(){
        tag_template = $(this).val();
            console.log(tag_template);
        //$(this).parent().parent().find('.tag_template').attr("id", tag_template);
        $(this).parent().parent().find('.tag_template').remove();
        $(this).parent().parent().find('td.delete_clase_tag_template').append('<input type="text" name="tag_text[]" class="tag_template" id="'+ tag_template +'" value=""/>');
        });
}); 


//смена полей ввода (тег поля)//


</script>

skitskis 23.01.2018 19:07

Вот тут можно посмотреть как работает, вывод в консоль настроен: https://codepen.io/Skitskis/pen/GyLddM

рони 23.01.2018 19:36

skitskis,
постаьте ваши click и change на то что есть всегда, table или form

$("table").on("click", ".add_tag", ....)

skitskis 23.01.2018 19:43

Цитата:

Сообщение от рони (Сообщение 476060)
skitskis,
постаьте ваши click и change на то что есть всегда, table или form

$("table").on("click", ".add_tag", ....)

add_tag у меня отрабатывает нормально. Проблема в том что при смене select, я не могу перехватить их val()


Часовой пояс GMT +3, время: 14:26.