Сделайте получение с помощью jQuery из динамических входных данных

#javascript #html #jquery

Вопрос:

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

Я думал запустить счетчик, и после каждой добавленной строки он будет увеличивать счетчик, не знаю, лучший ли это способ сделать

 var generalPreset = [{
  description: "This is item 1",
  amount: "30.00"
}, {
  description: "This is item 2",
  amount: "45.00"
}];
var discountPresets = [{
  description: "Siblings discount"
}, {
  description: "Annual relief"
}];
// receipt
var receipt = new Object();
$('#duedate').change(function() {
  receipt.duedate = $(this).val();
  $('.invoice-preview-card-duedate-value').text(receipt.duedate);
});

// for adding invoice item
$('.add-invoice-item').click(function() {
  $('.inv-table-body').append(`<div class="body-row row m-0">
            <div class="px-2 col-3">
                <select name="item_type[]" class="form-control invoiceType" required>
                    <option value="newitem">New Item</option>
                    <option value="presetitem">Present Item</option>
                    <option value="discount">Discount</option>
                    <option value="subsidy">Subsidy</option>
                </select>
            </div>
            <div class="px-2 col-6 item-description" style="display: flex;">
                <input type="text" class="form-control" name="description[]" placeholder="Add Invoice Description" required style="flex: 1">
            </div>
            <div class="px-2 col-2">
                <input type="number" class="form-control invoiceItemAmount" name="amount[]" value="" placeholder="0" required>
            </div>
            <div class="col-1 del-icon-container"><button class="del-invoice-item">Del</button></div>
        </div>
        `);
});

// for deleting invoice item
$(document).on('click', '.del-invoice-item', function() {
  $(this).closest('.body-row').remove();
});

// for description of invoice type change
$(document).on('change', '.invoiceType', function() {
  let $field = $(this);
  let invoiceType = $field.val(); // :selected not needed

  if (invoiceType === 'newitem') {
    $field.closest('.body-row').find('.item-description').html(`<input type="text" class="form-control" name="description[]" placeholder="Add Invoice Description" required style="flex: 1">`);
  } else if (invoiceType === 'presetitem') {
    var options;
    $.each(generalPreset, function(key, value) {
      options = options   '<option value="'   value.amount   '">'   value.description   '</option>';
    });
    $field.closest('.body-row').find('.item-description').html(`
        <select class="form-control general-presets" name="description[]" required style="flex: 1">
            <option></option>
            `  
      options  
      `
        </select>
        `);

  } else if (invoiceType === 'discount') {
    var dicountOptions;
    $.each(discountPresets, function(key, value) {
      dicountOptions = dicountOptions   '<option>'   value.description   '</option>';
    });

    $field.closest('.body-row').find('.item-description').html(`<div class="mr-2 divForCalculation" style="flex: 1">
            <div style="display: flex" class="calculation-container">
                <div class="mr-2" style="flex: 1">
                    <div class="input-group my-group">
                        <input type="text" class="form-control discountAmount" name="snpid" placeholder="0">
                        <select id="lunch" class="form-control amountOrPercent" style="padding: 4px;">
                            <option value="amount">

lt;/option>
<option value="percentage">%</option>
</select>
</div>
</div>
</div>
</div>
<select class="form-control discount-presets" name="description[]" required style="flex: 2">
<option></option>
`
dicountOptions
`
</select>
`);
} else if (invoiceType === 'subsidy') {
$field.closest('.body-row').find('.item-description').html(`<div class="mr-2 divForCalculation" style="flex: 1">
<div style="display: flex" class="calculation-container">
<div class="mr-2" style="flex: 1">
<div class="input-group my-group">
<input type="text" class="form-control discountAmount" name="snpid" placeholder="0">
<select id="lunch" class="form-control amountOrPercent" style="padding: 4px;">
<option value="amount">


lt;/option>
<option value="percentage">%</option>
</select>
</div>
</div>
</div>
</div>
<input type="text" class="form-control" name="description[]" placeholder="Add Invoice Description" required style="flex: 2">
`);
}
});

// populate invoice amount by preset items
$(document).on('change', '.general-presets', function() {
var presetSelectValue = $(this).find(":selected").val();
$(this).closest(".body-row").find(".invoiceItemAmount").val(presetSelectValue);
});

// Percentage or Amount structure change
$(document).on('change', '.amountOrPercent', function() {
var amountOrPercent = $(this).find(":selected").val();
if (amountOrPercent == 'amount') {
$(this).closest('.body-row').find('.extraForPercentage').remove();
$(this).closest('.body-row').find('.amountOrPercent').css('padding', '4px');
$(this).closest('.body-row').find('.divForCalculation').css('flex', '1');
} else if (amountOrPercent == 'percentage') {
$(this).closest('.body-row').find('.divForCalculation').css('flex', '2');
$(this).closest('.body-row').find('.amountOrPercent').css('padding', '0');
$(this).closest('.body-row').find('.calculation-container').append(`<div class="extraForPercentage" style="flex: 1">
<span class="mr-2 pt-2">Of</span>
<div style="display: inline;">
<input type="text" class="form-control totalof" placeholder="0" required style="display: inline; width: 60%;" value="">
</div>
</div>
`);
}
});

$(document).on("change keyup keypress", ".discountAmount, .totalof , .amountOrPercent", function() {
var selector = $(this).closest(".divForCalculation") //get closest div

var discountAmount = 0;
var discountPercentage = 0;
var totalof = 0;
var result = 0;
discountAmount = selector.find(".discountAmount").val();
totalof = selector.find(".totalof").val();

//added cond if not visible
if (totalof == null || totalof == 0 || !selector.find(".totalof").is(":visible")) {
totalof = 0;
//change value depending on select values
result = selector.find(".amountOrPercent").val() == "amount" ? -discountAmount : 0;
} else {
result = -parseFloat((parseInt(totalof) / 100 * parseInt(discountAmount)));
}

//use nextAll..
// selector.nextAll('.invoiceItemAmount').val(result);
$(this).closest(".body-row").find(".invoiceItemAmount").val(result);
});

 .invoice-preview-card-header {
    padding: 44px 24px;
}
.invoice-preview-card-body {
    padding: 18px 24px;
    background-color: #ebf2ef;
}
.invoice-preview-card-duedate-value {
    font-weight: bold;
}
.invoice-preview-card-table {
    margin-top: 12px;
}
.invoice-preview-card-table-header {
    padding: 10px 0;
    border-bottom: 1px solid #d8d8d8
}
.invoice-preview-card-table-column1 {
    width: 75%;
    display: inline-block;
}
.invoice-preview-card-table-column2 {
    width: 20%;
    display: inline-block;
}
.invoice-preview-card-table-body {
    border-bottom: 1px solid #d8d8d8;
}
.invoice-preview-card-table-row {
    padding-top: 12px;
}
.invoice-preview-card-table-row:last-child {
    padding-bottom: 12px;
}
.invoice-preview-card-table-body > .invoice-preview-card-table-row {
    font-weight: bold;
}
.invoice-preview-card-table-column2 {
    text-align: right;
}
.invoice-preview-card-table-footer {
    padding: 10px 0;
}
.invoice-preview-card-table-footer > .invoice-preview-card-table-column2 {
    font-weight: normal;
}
.invoice-preview-card-table-footer > .invoice-preview-card-table-column2 span{
    font-weight: bold;
} 
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="form-card">
  <div class="row">
    <div class="form-group col-md-4">
      <label for="">Invoice Due Date</label>
      <input type="date" class="form-control" name="duedate" id="duedate">  </div>

    <div class="form-group col-md-8">
      <div class="row mr-0">
        <label for="" class="col-12 pl-0">Date of Service(optional)</label>
        <input type="date" class="form-control col" name="service_start" id="">
        <span class="service-span">to</span>
        <input type="date" class="form-control col" name="service_end" id="">
      </div>
    </div>
  </div>

  <hr>

  <h5>Invoice Details</h5>
  <div class="card" style="border: 1px solid #d8d8d8;">
    <div class="inv-table">
      <div class="inv-table-head">
        <div class="head-row row m-0">
          <div class="px-2 col-3">Row</div>
          <div class="px-2 col-6">Description</div>
          <div class="px-2 col-2">Amount</div>
          <div class="px-2 col-1"></div>
        </div>
      </div>
      <div class="inv-table-body">
        <div class="body-row row m-0">
          <div class="px-2 col-3">
            <select name="invoice_type" class="form-control invoiceType" required>
              <option value="newitem">New Item</option>
              <option value="presetitem">Preset Item</option>
              <option value="discount">Discount</option>
              <option value="subsidy">Subsidy</option>
            </select>
          </div>
          <div class="px-2 col-6 item-description" style="display: flex;">
            <input type="text" class="form-control" name="description[]" placeholder="Add Invoice Description" required style="flex: 1">
          </div>
          <div class="px-2 col-2">
            <input type="number" class="form-control invoiceItemAmount" name="amount[]" placeholder="0" value="" required>
          </div>
          <div class="col-1 del-icon-container"><i class="fas fa-trash"></i></div>
        </div>
      </div>
      <div class="inv-table-footer">
        <div class="row">
          <div class="col-6">
            <span class="add-invoice-item">
                                                            <i class="fas fa-plus-circle"></i> ADD INVOICE ITEM
                                                        </span>
          </div>
          <div class="col-6">
            <span class="">
                                                            <b>Total: </b>

lt;span class="tatalAmountShow">0</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>

<br><br>
<hr>
<br>

<div class="invoice-preview-card-body">
<div class="invoice-preview-card-duedate">
Due Date: <span class="invoice-preview-card-duedate-value"></span>
</div>
<div class="invoice-preview-card-duedate">
Invoice Period: <span class="invoice-preview-card-duedate-value">May 1, 2021 - May 10, 2021</span>
</div>
<div class="invoice-preview-card-table">
<div class="invoice-preview-card-table-header">
<div class="invoice-preview-card-table-column1">
Description
</div>
<div class="invoice-preview-card-table-column2">
Amount
</div>
</div>
<div class="invoice-preview-card-table-body">
<div class="invoice-preview-card-table-row">
<div class="invoice-preview-card-table-column1">
This is item 1
</div>
<div class="invoice-preview-card-table-column2">
$30
</div>
</div>
<div class="invoice-preview-card-table-row">
<div class="invoice-preview-card-table-column1">
This is item 2
</div>
<div class="invoice-preview-card-table-column2">
$45
</div>
</div>
</div>
<div class="invoice-preview-card-table-footer">
<div class="invoice-preview-card-table-column1">
</div>
<div class="invoice-preview-card-table-column2">
Total <span>$0</span>
</div>
</div>
</div>
</div>

Пример
Это входные данные для элементов счета-фактуры

Чек
Сгенерированный чек

Комментарии:

1. Когда Description появилось % поле выбора, что должно быть в описании счета-фактуры ?

2. Он должен печатать только описание и значение суммы из входных данных счета-фактуры. % есть только скидка и субсидия, так что это только для расчета. Эти значения не поступают в квитанцию.

3. Но, когда пользователь выбирает опцию скидки, нет поля «Описание»? Потому что я вижу, что у всех остальных трех вариантов есть поле desc, но не для скидки . Можете ли вы привести пример вывода всех опций ?

4. @Swati Я добавил пример вывода, субсидия также совпадает со скидкой, но субсидия-это текстовое поле вместо выпадающего списка. Я не показывал этого в примере

Ответ №1:

Вы можете поместить всю часть расчета в отдельную функцию и вызывать ее при необходимости .Внутри этой функции вы можете использовать .each цикл для перебора body-row , затем получить значения внутри этого div и передать их в тег тела счета .

Демонстрационный код :

 var generalPreset = [{
  description: "This is item 1",
  amount: "30.00"
}, {
  description: "This is item 2",
  amount: "45.00"
}];
var discountPresets = [{
  description: "Siblings discount"
}, {
  description: "Annual relief"
}];
// receipt
var receipt = new Object();
$('#duedate').change(function() {
  receipt.duedate = $(this).val();
  $('.invoice-preview-card-duedate-value').text(receipt.duedate);
});

// for adding invoice item
$('.add-invoice-item').click(function() {
  $('.inv-table-body').append(`<div class="body-row row m-0">
            <div class="px-2 col-3">
                <select name="item_type[]" class="form-control invoiceType" required>
                    <option value="newitem">New Item</option>
                    <option value="presetitem">Present Item</option>
                    <option value="discount">Discount</option>
                    <option value="subsidy">Subsidy</option>
                </select>
            </div>
            <div class="px-2 col-6 item-description" style="display: flex;">
                <input type="text" class="form-control" name="description[]" placeholder="Add Invoice Description" required style="flex: 1">
            </div>
            <div class="px-2 col-2">
                <input type="number" class="form-control invoiceItemAmount" name="amount[]" value="" placeholder="0" required>
            </div>
            <div class="col-1 del-icon-container"><button class="del-invoice-item">Del</button></div>
        </div>
        `);
});

// for deleting invoice item
$(document).on('click', '.del-invoice-item', function() {
  $(this).closest('.body-row').remove();
  build_invoice() //call this
});

// for description of invoice type change
$(document).on('change', '.invoiceType', function() {
  let $field = $(this);
  let invoiceType = $field.val(); // :selected not needed

  if (invoiceType === 'newitem') {
    $field.closest('.body-row').find('.item-description').html(`<input type="text" class="form-control" name="description[]" placeholder="Add Invoice Description" required style="flex: 1">`);
  } else if (invoiceType === 'presetitem') {
    var options;
    $.each(generalPreset, function(key, value) {
      options = options   '<option value="'   value.amount   '">'   value.description   '</option>';
    });
    $field.closest('.body-row').find('.item-description').html(`
        <select class="form-control general-presets" name="description[]" required style="flex: 1">
            <option></option>
            `  
      options  
      `
        </select>
        `);

  } else if (invoiceType === 'discount') {
    var dicountOptions;
    $.each(discountPresets, function(key, value) {
      dicountOptions = dicountOptions   '<option>'   value.description   '</option>';
    });

    $field.closest('.body-row').find('.item-description').html(`<div class="mr-2 divForCalculation" style="flex: 1">
            <div style="display: flex" class="calculation-container">
                <div class="mr-2" style="flex: 1">
                    <div class="input-group my-group">
                        <input type="text" class="form-control discountAmount" name="snpid" placeholder="0">
                        <select id="lunch" class="form-control amountOrPercent" style="padding: 4px;">
                            <option value="amount">

lt;/option>
<option value="percentage">%</option>
</select>
</div>
</div>
</div>
</div>
<select class="form-control discount-presets" name="description[]" required style="flex: 2">
<option></option>
`
dicountOptions
`
</select>
`);
} else if (invoiceType === 'subsidy') {
$field.closest('.body-row').find('.item-description').html(`<div class="mr-2 divForCalculation" style="flex: 1">
<div style="display: flex" class="calculation-container">
<div class="mr-2" style="flex: 1">
<div class="input-group my-group">
<input type="text" class="form-control discountAmount" name="snpid" placeholder="0">
<select id="lunch" class="form-control amountOrPercent" style="padding: 4px;">
<option value="amount">


lt;/option>
<option value="percentage">%</option>
</select>
</div>
</div>
</div>
</div>
<input type="text" class="form-control" name="description[]" placeholder="Add Invoice Description" required style="flex: 2">
`);
}

});

// populate invoice amount by preset items
$(document).on('change', '.general-presets', function() {
var presetSelectValue = $(this).find(":selected").val();
$(this).closest(".body-row").find(".invoiceItemAmount").val(presetSelectValue);
build_invoice() //call this
});

// Percentage or Amount structure change
$(document).on('change', '.amountOrPercent', function() {
var amountOrPercent = $(this).find(":selected").val();
if (amountOrPercent == 'amount') {
$(this).closest('.body-row').find('.extraForPercentage').remove();
$(this).closest('.body-row').find('.amountOrPercent').css('padding', '4px');
$(this).closest('.body-row').find('.divForCalculation').css('flex', '1');
} else if (amountOrPercent == 'percentage') {
$(this).closest('.body-row').find('.divForCalculation').css('flex', '2');
$(this).closest('.body-row').find('.amountOrPercent').css('padding', '0');
$(this).closest('.body-row').find('.calculation-container').append(`<div class="extraForPercentage" style="flex: 1">
<span class="mr-2 pt-2">Of</span>
<div style="display: inline;">
<input type="text" class="form-control totalof" placeholder="0" required style="display: inline; width: 60%;" value="">
</div>
</div>
`);
}
});

$(document).on("change keyup keypress", ".discountAmount, .totalof , .amountOrPercent", function() {
var selector = $(this).closest(".divForCalculation") //get closest div

var discountAmount = 0;
var discountPercentage = 0;
var totalof = 0;
var result = 0;
discountAmount = selector.find(".discountAmount").val();
totalof = selector.find(".totalof").val();

//added cond if not visible
if (totalof == null || totalof == 0 || !selector.find(".totalof").is(":visible")) {
totalof = 0;
//change value depending on select values
result = selector.find(".amountOrPercent").val() == "amount" ? -discountAmount : 0;
} else {
result = -parseFloat((parseInt(totalof) / 100 * parseInt(discountAmount)));
}

//use nextAll..
// selector.nextAll('.invoiceItemAmount').val(result);
$(this).closest(".body-row").find(".invoiceItemAmount").val(result);
build_invoice() //call this
});

function build_invoice() {
$(".invoice-preview-card-table-body").html("")
var total = 0
console.clear()
//loop through body-row
$(".inv-table-body > .body-row").each(function() {
//because genral slect value="number" that's why text
var desc = $(this).find(".item-description [name*='description']").hasClass("general-presets") ? $(this).find(".item-description [name*='description']").find("option:selected").text() : $(this).find(".item-description [name*='description']").val();
//get amt
var amt = $(this).find(".invoiceItemAmount").val() != "" ? $(this).find(".invoiceItemAmount").val() : 0
//append in body
$(".invoice-preview-card-table-body").append(`<div class="invoice-preview-card-table-row">
<div class="invoice-preview-card-table-column1">
${desc}
</div>
<div class="invoice-preview-card-table-column2">
${amt}
</div>
</div>`)
total = parseFloat(amt) //for total
})
$("#to_inv").text("$" total) //add total

}

 .invoice-preview-card-header {
  padding: 44px 24px;
}

.invoice-preview-card-body {
  padding: 18px 24px;
  background-color: #ebf2ef;
}

.invoice-preview-card-duedate-value {
  font-weight: bold;
}

.invoice-preview-card-table {
  margin-top: 12px;
}

.invoice-preview-card-table-header {
  padding: 10px 0;
  border-bottom: 1px solid #d8d8d8
}

.invoice-preview-card-table-column1 {
  width: 75%;
  display: inline-block;
}

.invoice-preview-card-table-column2 {
  width: 20%;
  display: inline-block;
}

.invoice-preview-card-table-body {
  border-bottom: 1px solid #d8d8d8;
}

.invoice-preview-card-table-row {
  padding-top: 12px;
}

.invoice-preview-card-table-row:last-child {
  padding-bottom: 12px;
}

.invoice-preview-card-table-body>.invoice-preview-card-table-row {
  font-weight: bold;
}

.invoice-preview-card-table-column2 {
  text-align: right;
}

.invoice-preview-card-table-footer {
  padding: 10px 0;
}

.invoice-preview-card-table-footer>.invoice-preview-card-table-column2 {
  font-weight: normal;
}

.invoice-preview-card-table-footer>.invoice-preview-card-table-column2 span {
  font-weight: bold;
} 
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="form-card">
  <div class="row">
    <div class="form-group col-md-4">
      <label for="">Invoice Due Date</label>
      <input type="date" class="form-control" name="duedate" id="duedate"> </div>

    <div class="form-group col-md-8">
      <div class="row mr-0">
        <label for="" class="col-12 pl-0">Date of Service(optional)</label>
        <input type="date" class="form-control col" name="service_start" id="">
        <span class="service-span">to</span>
        <input type="date" class="form-control col" name="service_end" id="">
      </div>
    </div>
  </div>

  <hr>

  <h5>Invoice Details</h5>
  <div class="card" style="border: 1px solid #d8d8d8;">
    <div class="inv-table">
      <div class="inv-table-head">
        <div class="head-row row m-0">
          <div class="px-2 col-3">Row</div>
          <div class="px-2 col-6">Description</div>
          <div class="px-2 col-2">Amount</div>
          <div class="px-2 col-1"></div>
        </div>
      </div>
      <div class="inv-table-body">
        <div class="body-row row m-0">
          <div class="px-2 col-3">
            <select name="invoice_type" class="form-control invoiceType" required>
              <option value="newitem">New Item</option>
              <option value="presetitem">Preset Item</option>
              <option value="discount">Discount</option>
              <option value="subsidy">Subsidy</option>
            </select>
          </div>
          <div class="px-2 col-6 item-description" style="display: flex;">
            <input type="text" class="form-control" name="description[]" placeholder="Add Invoice Description" required style="flex: 1">
          </div>
          <div class="px-2 col-2">
            <input type="number" class="form-control invoiceItemAmount" name="amount[]" placeholder="0" value="" required>
          </div>
          <div class="col-1 del-icon-container"><i class="fas fa-trash"></i></div>
        </div>
      </div>
      <div class="inv-table-footer">
        <div class="row">
          <div class="col-6">
            <span class="add-invoice-item">
                                                            <i class="fas fa-plus-circle"></i> ADD INVOICE ITEM
                                                        </span>
          </div>
          <div class="col-6">
            <span class="">
                                                            <b>Total: </b>

lt;span class="tatalAmountShow">0</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>

<br><br>
<hr>
<br>

<div class="invoice-preview-card-body">
<div class="invoice-preview-card-duedate">
Due Date: <span class="invoice-preview-card-duedate-value"></span>
</div>
<div class="invoice-preview-card-duedate">
Invoice Period: <span class="invoice-preview-card-duedate-value">May 1, 2021 - May 10, 2021</span>
</div>
<div class="invoice-preview-card-table">
<div class="invoice-preview-card-table-header">
<div class="invoice-preview-card-table-column1">
Description
</div>
<div class="invoice-preview-card-table-column2">
Amount
</div>
</div>
<div class="invoice-preview-card-table-body">

</div>
<div class="invoice-preview-card-table-footer">
<div class="invoice-preview-card-table-column1">
</div>
<div class="invoice-preview-card-table-column2">
Total <span id="to_inv">$0</span>
</div>
</div>
</div>
</div>

Комментарии:

1. Я создал 2 New Items , но результат не отображается, он отображается только тогда, когда я выбираю какой-либо предустановленный элемент

2. Вам нужно запускать эту функцию всякий раз, когда вам нужно записать событие изменения в desp, а также вызывать эту функцию оттуда .

3. Большое вам спасибо, кстати, мне нравится ваше имя @Swati 🙂