3

This is What I have :

I have a text box input element as below for loading cities autoloaded and a hidden field to list its ids:

<label class="col-sm-2 control-label" for="city_disp"> City</label>
<div class="col-sm-5">
  <div class="input-group">
    <input type="hidden" class="hidden_value" name="city" id="city" value="" />
    <input type="text" name="city_disp" placeholder="City" 
        id="city_disp" data-request_type="cities" value=""
        class="form-control autocomplete-input-field" autocomplete="off" />
  </div>
</div>

jQuery UI AutoComplete which I use, the data array comes from Ajax response :

            function split( val ) {
                        return val.split( /,\s*/ );
            }
            function extractLast( term ) {
                        return split( term ).pop();
            }

            $(".autocomplete-input-field").autocomplete({
                     source: function (request, response) {
                                     $this = this.element;
                                     var term = extractLast(request.term);
                                     $.ajax({
                                              url: myHome+'/my_ajax',
                                              dataType: "json",
                                              type: "POST",
                                              data: {
                                                      term: term,
                                                      action_type: "getdata"
                                               },
                                               success: function (data) {
                                                                    response(data);
                                               }
                                   });
                     },
            minLength: 2,
            select: function (event, ui) {
                      var tempval =  $(this).val() ;
                      var terms = split( this.value );
                      var split_string = split( 
                      $(this).closest('div').find('.hidden_value').val() );
                      split_string.pop();
                      terms.pop();
                      terms.push( ui.item.label );
                      split_string.push( ui.item.value );
                      terms.push( "" );
                      split_string.push( "" );
                      var labels = terms.join( ", " );
                      var new_vals = split_string.join( "," );
                      $(this).val(labels);
                      $(this).closest('div').find('.hidden_value').val(new_vals);
                      return false;
                     },
                      focus: function (event, ui) {
                                  event.preventDefault();
                      }
            });

Output I am getting currently:

Currently,autocomplete is working fine when I type atleast 2 characters in the text box name="city_disp" . If user selects 3 values from the autocomplete cities list: 'New York,Washington,London' and the ids corresponding to these cities '45,56,78' gets appended to the hidden html input field name="city".

Modification which I am trying to implement :

Suppose if user selects 'New York,Washington,London' and its id gets '45,56,78' gets appended to the hidden html input field name="city". and the user removes a Washington from the selected values . Then the hidden value must also change accordingly to '45,78'. Also when a user omits Washington to some absurd characters like 'dasdsad' ,then how to handle such situations with this jQuery UI AutoComplete?

4
  • Why not delay the collection of the selected values until the hidden value is needed? I suppose it is submitted with the form? Could you not do this task on submission? Commented Jun 7, 2022 at 11:46
  • It would be good if its handled using jquery itself so as to be user friendly and not to accept any typo errors from the user Commented Jun 8, 2022 at 4:11
  • Sure, but that doesn't answer my suggestion. On submission you can execute JavaScript. Commented Jun 8, 2022 at 5:25
  • You might consider setting up an Array of Objects that can store the selected IDs and Names. This way when a item is removed, the corresponding element in the Array can be removed. Then, when the Form is submitted, the IDs can be added back to the Form Data or add to an element. Commented Jun 8, 2022 at 21:46

1 Answer 1

0

There is not a good way to do this with two unique lists of text. there becomes no relationship between the two except for the positioning. When the User removes and item from List A, how do you identify in List B the change, and align the lists.

Consider moving the selected items to a new User interface with the ID attached.

Example: https://jsfiddle.net/Twisty/m3vfk0hg/

HTML

<label class="col-sm-2 control-label" for="city_disp"> City</label>
<div class="col-sm-5">
  <div class="input-group">
    <input type="hidden" class="hidden_value" name="city" id="city" />
    <input type="text" name="city_disp" placeholder="City" id="city_disp" data-request_type="cities" class="form-control autocomplete-input-field" autocomplete="off" />
  </div>
  <div class="selected"></div>
</div>

Mostly the same HTML, yet now we have a section to display the Selected items, after they have been selected.

CSS

.selected {
  margin: 3px;
}

.selected-item {
  border: 1px solid #00f;
  border-radius: 6px;
  padding: 3px;
  background: #ccf;
  margin: 3px;
}

.selected-item .btn-close {
  margin-left: 6px;
}

Giving us some Style.

JavaScript

$(function() {

  var myAutoData = [{
      label: "New York",
      value: "45"
    }, {
      label: "Washington",
      value: "56"
    },
    {
      label: "London",
      value: "78"
    }
  ];

  function newItem(it) {
    var item = $("<span>", {
      class: "selected-item",
      "data-id": it.value
    }).html(it.label);
    $("<span>", {
      class: "btn-close"
    }).appendTo(item);
    if ($("#city").val().length > 0) {
      $("#city").val($("#city").val() + "," + it.value);
    } else {
      $("#city").val(it.value);
    }
    return item;
  }

  $(".autocomplete-input-field").autocomplete({
    source: function(request, response) {
      var term = request.term;
      $.ajax({
        url: "/echo/json/",
        dataType: "json",
        type: "POST",
        data: {
          json: JSON.stringify(myAutoData),
          term: term
        },
        success: function(data) {
          response(data);
        }
      });
    },
    minLength: 2,
    select: function(event, ui) {
      $(this).parent().parent().find(".selected").append(newItem(ui.item));
      $(this).val("");
      return false;
    },
    focus: function(event, ui) {
      event.preventDefault();
    }
  });

  $(".selected").on("click", ".btn-close", function() {
    var id = $(this).parent().data("id");
    $(this).parent().remove();
    var sel = $("#city").val().split(",");
    sel = sel.splice(sel.indexOf(id), 1);
    $("#city").val(sel.join(","));
  });
});

The example uses the JSFiddle options to Echo back JSON data Posted to it. You will want to use your own url and data. I also setup some basinc exmaple items based on your post.

When the User types in a option, wash, they get options they can select. When they click on a selection a new item is created.

<span class="selected-item" data-id="56">Washington<span class="btn-close"></span></span>

This element is appended to the .selected element. This help prevent the user from entering dasdsad, this would return no results, and they cannot select anything.

If the User decides to remove a previously selected item, they click the x and it is removed. Behind the scene, as they make selections, the value of #city is updated to a list of IDs, 56,45. When the User removes an item, the list is updated, and that entry is removed. This is done by converting the list into an Array and using Splice to remove the matching element.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.