Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 26.09.2020, 10:08
l30 l30 вне форума
Интересующийся
Отправить личное сообщение для l30 Посмотреть профиль Найти все сообщения от l30
 
Регистрация: 26.09.2020
Сообщений: 11

Динамически создаваемая форма с подсчетом суммы
Добрый день!
Подскажите есть динамически создаваемая форма:
<div class="row">
    <div class="col-1">№</div>
    <div class="col-4">Номенклатура</div>
    <div class="col-1">Кол-во</div>
    <div class="col-2">Цена</div>
    <div class="col-2">Сумма</div>
    <div class="col-2"></div>
  </div>
  <div class="row">
    <div data-container="set">
    <div class="row p-2" data-item="set">
      <div class="col-1"><input type="text" value="" name="str[]" value=""></div>
     <div class="col-4"> <input type="text"  name="name[]" value=""></div>
      <div class="col-1"> <input type="text"  name="num[]" value=""></div>
       <div class="col-2"> <input type="text"  name="price[]" value=""></div>
     <div class="col-2"> <input type="text"  name="sum[]" value="" readonly></div>
 
     <div class="col-2"> <a type="button" data-action="remove" class="remove">[-]</a>
      <a type="button" data-action="add" class="add">[+]</a>
     </div>
    </div>
  </div>
  </div>
  <div class="row">
    <div class="col text-right"><hr>
    <label>Итого: <input type="text"  name="totalsum" value="" class="total" readonly></label>
    </div>
  </div>


И скрипт JS:

$(function () {
 
  var $container = $('[data-container="set"]'),
    $row = $container.find('[data-item="set"]').clone(true),
    $totalsum = $('[name="totalsum"]');
 
  $(document) 
    .on('click', '[data-action="add"]', function () {
      var $clone = $row.clone(true);  
 
      $container.append($clone);
      $clone.find('input[name]').eq(0).trigger('focus');
    })
    .on('click', '[data-action="remove"]', function () {
      var $parent = $(this).closest('[data-item="set"]');
 
      $totalsum.val($totalsum.val() - $parent.find('[name="sum[]"]').val());
      $parent.remove();
    })
    .on('input', '[name="num[]"], [name="price[]"]', function () {
      var $item = $(this),
        $parent = $item.closest('[data-item="set"]'),
        cost = parseFloat($parent.find('[name="num[]"]').val()),
        amount = parseFloat($parent.find('[name="price[]"]').val());
 
      $item.val($item.val().replace(/[^\d\.]/g, '').replace(/^\.+/g, '0.').replace(/^(\d+\.\d+)\.[\d\.]*$/g, '$1'));
 
      if (isFinite(cost) && isFinite(amount)) {
        var $sum = $parent.find('[name="sum[]"]'),
          prev = parseFloat($sum.val()) || 0,
          next = (cost * amount).toFixed(2),
          totalPrev = parseFloat($totalsum.val()) || 0;
 
        $totalsum.val((totalPrev + parseFloat(next) - prev).toFixed(2));
        $sum.val(next);
      }
    });
});


мне нужно чтобы все значениея прописывались в value, чтобы передать их в php. Как это сделать?
И еще хотелось бы чтобы поле № автоматически при добавлении нового поля присваивался порядковый номер (1,2,3 и т.д.)
Как это можно реализовать подскажите?
Ответить с цитированием
  #2 (permalink)  
Старый 26.09.2020, 10:58
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Сообщение от l30
мне нужно чтобы все значениея прописывались в value, чтобы передать их в php
Какие значения, разве не пользователь их вводит?
Ответить с цитированием
  #3 (permalink)  
Старый 26.09.2020, 10:59
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,109

Сообщение от l30
присваивался порядковый номер
https://webformyself.com/rukovodstvo-po-css-counter/
Ответить с цитированием
  #4 (permalink)  
Старый 26.09.2020, 16:10
l30 l30 вне форума
Интересующийся
Отправить личное сообщение для l30 Посмотреть профиль Найти все сообщения от l30
 
Регистрация: 26.09.2020
Сообщений: 11

Сообщение от laimas Посмотреть сообщение
Какие значения, разве не пользователь их вводит?
Да пользователь, но в php попадают значения только из первой строки, которая по дефолту появляется, но если пользователь добавляет еще несколько строк, они уже не попадают
Ответить с цитированием
  #5 (permalink)  
Старый 26.09.2020, 22:51
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Сообщение от l30
в php попадают значения только из первой строки, которая по дефолту появляется
Чего-то не то. Давайте так - данные уж точно будут писаться в базу, и такой переданный массив выгоднее писать в нее в пакетном режиме (многострочная вставка). Ограничения в таком режиме накладываются не на количество строк, а на их общий размер, и определяется sql-параметром max_allowed_packet. А учитывая то, что в базе каждая запись должна иметь свой уникальный идентификатор и формирование такового, это есть сам механизм SQL, а никак не нумерация клиентом, и записи в базу не только добавляются, но могут и удаляться из нее, наличие в ваших данных поля name="str[]", это нечто непонятное и никчемное.

То же самое можно сказать и о поле name="sum[]" - это какую же сумму нужно рассчитывать на клиенте, отправлять на север для сохранения в базе, если такие данные как количество и цена никогда не являлись величинами постоянными?

Я выбрасываю эти поля из данных, и все что нужно делать на клиенте, это:
- клонировать родительский узел
- найти в клоне поля и очистить их значения
- у кнопки удаления удалить класс remove, ибо этому классу по умолчанию указано быть невидимым, так как нельзя удалять из формы поля, если их набор в ней единственный
- вставить клон в родительский узел (в примере, это добавленный id="parent-box"), ему же делегируется и обработка кнопок удаления/добавления полей.

Как видите, если выполнить, отправив форму (добавлено для примера), то все добавленные наборы отправляются и ничего не пропадает.

<html>
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<style>
.remove {
    display: none;
}
</style>
<script type="text/javascript">
$(function() {
$('#parent-box').on('click', 'a', function(e) {
    e.preventDefault();
    
    var src = $(this), dst = src.closest('.row');
    
    if(src.hasClass('add')) {
        dst.clone()
           .find('input').val('')
           .end()
           .find('a').removeClass('remove')
           .end()
           .appendTo(e.delegateTarget)
    } else dst.remove();

});

$('form').submit(function(e) {
    e.preventDefault();
    alert(JSON.stringify($(this).serializeArray(), null, 4))
})    
});
</script>
</head>
<body>
<form>
<div id="parent-box">

  <div class="row">
    <div data-container="set">
    <div class="row p-2" data-item="set">
     <div class="col-4"> <input type="text"  name="name[]" value=""></div>
      <div class="col-1"> <input type="text"  name="num[]" value=""></div>
      <div class="col-2"> <input type="text"  name="price[]" value=""></div>
     
     <div class="col-2"> <a type="button" data-action="remove" class="remove">[-]</a>
      <a type="button" data-action="add" class="add">[+]</a>
     </div>
    </div>
  </div>
  </div>


</div>

<button>GO</button>
</form>
</body>
</html>


Но можно и "нумерацией" на клиенте заняться, но с совсем иной целью. Если на сервере при добавлении в базу используют ненумерованные метки, то пришедший массив данных:

Array
(
    [name] => Array
        (
            [0] => value
            [1] => value
            .....
        )

    [num] => Array
        (
            [0] => value
            [1] => value
            .....
        )

    [price] => Array
        (
            [0] => value
            [1] => value
            .....
        )
)


несложно преобразовать в массив для пакетной записи, как

$post = array_map(null, $_POST['name'], $_POST['num'], $_POST['price']);


получив массив:

Array
(
    [0] => Array
        (
            [0] => value
            [1] => value
            [2] => value
        )

    [1] => Array
        (
            [0] => value
            [1] => value
            [2] => value
        )
        .....
)


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

name="data[0][name]"
name="data[0][num]"
name="data[0][price]"

код добавления полей заменить на:

if(src.hasClass('add')) {
        var i = Date.now(); 
        dst.clone()
           .find('input').each(function() {
                this.value = '';
                this.name = this.name.replace(/\d+/, i) 
           })
           .end()
           .find('a').removeClass('remove')
           .end()
           .appendTo(e.delegateTarget)
    } else dst.remove();


то на сервере массив данных уже будет вот таким:

Array
(
    [data] => Array
        (
            [0] => Array
                (
                    [name] => value
                    [num] => value
                    [price] => value
                )

            [1601149425635] => Array
                (
                    [name] => value
                    [num] => value
                    [price] => value
                )

            [1601149432956] => Array
                (
                    [name] => value
                    [num] => value
                    [price] => value
                )
             .....
        )
)


получаем $_POST['data'] для дальнейшей работы с данными, и эта структура выгоднее. Здесь метка времени используется как индекс вложенных массивов, что проще чем вычислять какой-то номер, а на сервере он не имеет никакого практического значения.

Последний раз редактировалось laimas, 27.09.2020 в 03:26.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск