Home > Back-end >  Why value is deleted after alert pop up says that it can not be deleted?
Why value is deleted after alert pop up says that it can not be deleted?

Time:02-02

Hello i have made a dynamic add and remove input fields and the code works great except the part when you reach the maximum limit to delete fields, this is my code:

function rmv()
    {
        var count = document.getElementsByTagName('input');
        if(count.length > 6){
            $(document).on('click', '#rmvbtn', function () {
                $(this).closest('#dynamic').remove();
            });
        }else{
            alert('Order must have minimum one product-1');
        }
    }

When the alert shows up and i click okay the last field is deleted, i tried debugging the code to see if it enters in the delete function after i press okay but it does not. The reason there is a 6 is because there are 6 fields by default and user can add more and delete the new added but not the 6 default ones. So this error is deleting fields from the default part.

This is the html part its an edit panel where user can edit orders made for a client, this part is made with Laravel. The rows are printed as much times as many order prodcuts exist so each duplicated row has a button next to it to delete that specific row, this is the code:

@foreach($orders->products as $product)
                                <div id="olddynamic">
                                <div >
                                    <label for="products" >{{ __('Product') }}</label>
                                    <div >
                                        <select name="products[]" id="products" type="text"  required autocomplete="products">
                                            <option value="" selected="true" disabled>{{$product->name}}</option>

                                            @foreach($productList as $item)
                                                <option value="{{$item->id}}">{{$item->name}}</option>
                                            @endforeach
                                        </select>

                                        @error('products')
                                        <span  role="alert">
                                        <strong>{{ $message }}</strong>
                                        </span>
                                        @enderror
                                    </div>
                                </div>

                                <div >

                                    <label for="amount" >{{ __('Amount') }}</label>

                                    <div >
                                        <input id="amount" type="text" 
                                               name="amount[]" value="{{ $product->pivot->amount }}" required autocomplete="amount">

                                        @error('amount')
                                        <span  role="alert">
                                        <strong>{{ $message }}</strong>
                                        </span>
                                        @enderror
                                    </div>
                                </div>
                                <div ><button type="button" id="oldrmvbtn" onclick="oldrmv()" ><span ></span></button></div>
                                </div>
                            @endforeach

There is also this add row button that adds new rows to the existing order this is the code:

<div ><button type="button" id="addbtn" onclick="add()" ><span ></span></button></div>

This is the whole Javascript code:

<script>
    function add()
    {
        $('#amm').append(
            '<div id="dynamic"><div ><label for="products" >{{ __("Product") }}</label><div ><select name="products[]" id="products" type="text" products") is-invalid @enderror" required autocomplete="products">@foreach($productList as $item)<option value="{{$item->id}}">{{$item->name}}</option>@endforeach</select>@error("products")<span  role="alert"><strong>{{ $message }}</strong></span>@enderror</div></div>  <div ><label for="amount" >{{ __("Amount") }}</label><div ><input id="amount" type="text" amount") is-invalid @enderror" name="amount[]" required autocomplete="amount">@error("amount")<span  role="alert"><strong>{{ $message }}</strong></span>@enderror</div></div> <div ><button type="button" id="rmvbtn" onclick="rmv()" ><span ></span></button></div> </div>'
        );
    }

    function rmv()
    {
        var count = document.getElementsByTagName('input');
        if(count.length > 6){
            $(document).on('click', '#rmvbtn', function () {
                $(this).closest('#dynamic').remove();
            });
        }else{
            alert('Order must have minimum one product-1');
        }
    }

    function oldrmv()
    {
        var count = document.getElementsByTagName('input');
        if(count.length > 6){
            $(document).on('click', '#oldrmvbtn', function () {
                $(this).closest('#olddynamic').remove();
            });
            alert(count.length);
        }else{
            alert('Order must have minimum one product-2');
        }
    }
</script>

CodePudding user response:

Please delete onclick="add()", onclick="rmv()" and onclick="oldrmv()" in HTML.

After change Javascript

$(document).ready(function() {
    $(document).on('click', '#addbtn', function () {
        $('#amm').append(
            '<div id="dynamic"><div ><label for="products" >{{ __("Product") }}</label><div ><select name="products[]" id="products" type="text" products") is-invalid @enderror" required autocomplete="products">@foreach($productList as $item)<option value="{{$item->id}}">{{$item->name}}</option>@endforeach</select>@error("products")<span  role="alert"><strong>{{ $message }}</strong></span>@enderror</div></div>  <div ><label for="amount" >{{ __("Amount") }}</label><div ><input id="amount" type="text" amount") is-invalid @enderror" name="amount[]" required autocomplete="amount">@error("amount")<span  role="alert"><strong>{{ $message }}</strong></span>@enderror</div></div> <div ><button type="button" id="rmvbtn" onclick="rmv()" ><span ></span></button></div> </div>'
        );
    });

    $(document).on('click', '#rmvbtn', function () {
        let count = document.getElementsByTagName('input');
        if(count.length > 6){
                $(this).closest('#dynamic').remove();
        }else{
            alert('Order must have minimum one product-1');
        }
    });

    $(document).on('click', '#oldrmvbtn', function () {
        let count = document.getElementsByTagName('input');
        if(count.length > 6){
            $(this).closest('#olddynamic').remove();
        }else{
            alert('Order must have minimum one product-2');
        }
    });
});

CodePudding user response:

The main issue is due to the nested click event handler within the rmv() function. You should remove that and use a single delegate event handler for the dynamic content.

That being said, there's quite a few other things you can do to improve the code quality here:

  • Avoid putting HTML in your JS. If you do include HTML in the JS, it should absolutely not be an entire multi-line structure. Use a <template> to store it.
  • Remove the id attributes in the content which can be dynamically repeated, otherwise you'll create duplicates which will cause problems. Change them to classes instead.
  • The 'Remove' logic is broken, assuming that your intention is to ensure there is always at least 1 item added - as the error message states.

With that said, try this working version:

const $container = $('#amm');
const $template = $('#amm-template');

$('#add').on('click', () => {
  $container.append($template.html());
});

$container.on('click', '.rmvbtn', e => {
  if ($('.amm-item').length > 1) {
    $(e.target).closest('.amm-item').remove();
  } else { 
    alert('Order must have minimum one product-1');
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<button id="add">Add</button>
<div id="amm"></div>

<template id="amm-template">
  <div >
    <div ><label for="products" >{{ __("Product") }}</label>
      <div >
        <select name="products[]" type="text" products") is-invalid @enderror" required autocomplete="products">
          @foreach($productList as $item)
            <option value="{{$item->id}}">{{$item->name}}</option>
          @endforeach
        </select>
        @error("products")
          <span  role="alert"><strong>{{ $message }}</strong></span>
        @enderror
      </div>
    </div>
    <div >
      <label for="amount" >{{ __("Amount") }}</label>
      <div >
        <input type="text" amount") is-invalid @enderror" name="amount[]" required autocomplete="amount">
        @error("amount")
          <span  role="alert"><strong>{{ $message }}</strong></span>
        @enderror
      </div>
    </div>
    <div >
      <button type="button"  >
        <span >REMOVE</span>
      </button>
    </div>
  </div>
</template>

  • Related