How to prevent from data looping in jQuery Ajax?

Viewed 232

This is regarding assigning multiple user using Select2 plugin, Ajax and API. The situation, I have a function that contain of 2 Ajax with different pointed URL. Currently, I have pre-selected user that stored in DB. The selection is using Select2 in a Modal. So what is happen now when Modal is opened, 1st Ajax will load URL /all_user to display all user in DB. After that 2nd Ajax will load URL /activity to get and load information for other fields in the same Modal. Both URLs are running in parallel.

URL /all_user successful to display all user. URL /activity also successful to display pre-selected user. However, when I close the Modal and re-open back the same Modal without refresh page, it will definitely load the same function that contain 2 Ajax as mentioned above.

FYI, in /activity I have doing a function to convert from String to Array since I received in String from DB, so need to convert before displaying in Select.

So the problem is both are the data will be duplicate 2x, when I close and re-open, it will duplicate 3x. How to prevent from the duplication?

Below are the pre-selected Select2 in /activity.

enter image description here

Below are the /all_user that successfully display all user

enter image description here

So when Modal is close and re-open back, duplication happen.

enter image description here

HTML

<select type="text" class="form-control mySelect" id="editOwner" name="editOwner" multiple="multiple"></select>

SELECT2 INIT

var mySelect = $('.mySelect').select2({
   allowClear: true,
   placeholder: "Search Owner...",
   minimumResultsForSearch: -1,
   width: 600,
});

JS

<span onclick='editOwner(&quot;"+value3.l3_id+"&quot;)'></span>

function editOwner(id){

    activity_id = id;

    $.ajax ({
        url: '/all_user',
        crossDomain: true,
        type: "POST",
        dataType : 'json',
        cache: false,
        processData: true,
        data: 'data',
        success: function(response){
            for (var i = 0; i < response.data.length; i++) { 
                $("#editOwner").append($("<option>", {
                    response: response.data[i].fullname,
                    text: response.data[i].fullname
                }));
            }
        }
    });

    $.ajax({
        url : '/activity',
        crossDomain: true,
        type: "POST",
        dataType : 'json',
        cache: false,
        processData: true,
        data: {task_id: activity_id}},
        success: function(response){
                if (response.status == "Success"){
                    $("#editOwner").val(response.data[0]["task_owner"]).attr("readonly",false);

                    $(response.data).each(function(key,value){
                        var owners = value.task_owner.split(',');
                        $(owners).each(function(k,v){
                            $("#editOwner").append($("<option selected>", {
                                response: v,
                                text: v
                            }));
                        });
                        $("#editOwner").val(owners).trigger("change");
                    });

                }
                else {}
        },
        error: function(e){}
    });

    $('#editOwnerModal').modal('show');    
}
1 Answers

This is because you are calling:

editOwner(id);

on the click event of your your span that contains your select with the ID of #editOwner.

Like this:

  <body>
    <select id="cars" style="display: block">
      <option value="volvo">Volvo</option>
      <option value="saab">Saab</option>
      <option value="opel">Opel</option>
      <option value="audi">Audi</option>
    </select>

    <script type="text/javascript" src="jquery-3.4.1.min.js"></script>
    <script type="text/javascript">
      function addCar ()
      {
        $("#cars").append
        (
          $("<option>", { response: "Ford", text: "Ford" })
        );
      }

      $("#cars").on
      (
        "click",
        addCar
      );

    </script>
  </body>

Every time you open and close the select element with the ID of #editOwner your appending a new option to the select element. You can easily fix this by adding:

$("#editOwner").unbind();

Like this:

  <body>
    <select id="cars" style="display: block">
      <option value="volvo">Volvo</option>
      <option value="saab">Saab</option>
      <option value="opel">Opel</option>
      <option value="audi">Audi</option>
    </select>

    <script type="text/javascript" src="jquery-3.4.1.min.js"></script>
    <script type="text/javascript">
      function addCar ()
      {
        $("#cars").append
        (
          $("<option>", { response: "Ford", text: "Ford" })
        );

        // Add this to remove the onclick events for #cars so it will only run one time.
        $("#cars").unbind();
      }

      $("#cars").on
      (
        "click",
        addCar
      );
    </script>
  </body>

Or better yet you could only have the function run one time by not calling it with a onclick event at all like this:

  <body>
    <select id="cars" style="display: block">
      <option value="volvo">Volvo</option>
      <option value="saab">Saab</option>
      <option value="opel">Opel</option>
      <option value="audi">Audi</option>
    </select>

    <script type="text/javascript" src="jquery-3.4.1.min.js"></script>
    <script type="text/javascript">
      function addCar ()
      {
        $("#cars").append
        (
          $("<option>", { response: "Ford", text: "Ford" })
        );
      }
    </script>

    <script type="text/javascript">
      addCar();
    </script>
  </body>

Unless there is a reason you need to call your ajax with a onclick event you really shouldn't, but if you need to you should call $("#editOwner").unbind(); at the end of editOwner(id); like this:

Edit: Saw that you were calling editOwner(id) with a span that had a onclick event. Just add an ID to that and call $("#mySpan").prop("onclick", null).off("click");

      <span id="#mySpan" onclick='editOwner(&quot;"+value3.l3_id+"&quot;)'></span>

      function editOwner(id){

      activity_id = id;

      $.ajax ({
          url: '/all_user',
          crossDomain: true,
          type: "POST",
          dataType : 'json',
          cache: false,
          processData: true,
          data: 'data',
          success: function(response){
              for (var i = 0; i < response.data.length; i++) { 
                  $("#editOwner").append($("<option>", {
                      response: response.data[i].fullname,
                      text: response.data[i].fullname
                  }));
              }
          }
      });

      $.ajax({
          url : '/activity',
          crossDomain: true,
          type: "POST",
          dataType : 'json',
          cache: false,
          processData: true,
          data: {task_id: activity_id}},
          success: function(response){
                  if (response.status == "Success"){
                      $("#editOwner").val(response.data[0]["task_owner"]).attr("readonly",false);

                      $(response.data).each(function(key,value){
                          var owners = value.task_owner.split(',');
                          $(owners).each(function(k,v){
                              $("#editOwner").append($("<option selected>", {
                                  response: v,
                                  text: v
                              }));
                          });
                          $("#editOwner").val(owners).trigger("change");
                      });

                  }
                  else {}
          },
          error: function(e){}
      });

      $('#editOwnerModal').modal('show');   

      // Try adding this.
      //$("#editOwner").unbind();

      // Or this if you want to use onclick as an attribute.
      $("#mySpan").prop("onclick", null).off("click");

  }
Related