0

I am new to javascript and jquery. I am trying to create an autocomplete jqueryui with model data as its source. I am stuck at what is the best way of how to do this. I have tried to initialise the data in document.ready like this:

           var listAddress = [];

           foreach (var item in Model.allBuildings)
          {              


          //adding into address array all addresses for label  and its id.


          @: listAddress.push({ label: "@Html.Raw(item.Address)", id: "@item.ApartmentBlockID" });*@

          }

The autocomplete works, but I keep getting messages from developer tools that

         Violation] 'setTimeout' handler took 113ms

My question is what is a better way to use model data as source for autocomplete? My biggest puzzle is that I have not set anywhere a settimeout function! The error is pointing to the settimeout function in the jqueryui script??

Update: This is my view

      // first autocomplete

        <div class="col-md-10">
        @Html.HiddenFor(model => model.renovationDetail.ApartmentBlockID, new { @id = "hidden_apartblockID" })
        @Html.EditorFor(model => model.BuildingID, new { htmlAttributes = new { @class = "form-control", @id = "show_buildingID" } })
        @Html.ValidationMessageFor(model => model.renovationDetail.ApartmentBlockID, "", new { @class = "text-danger" })
    </div>
</div>


          //second autocomplete
         <div class="form-group">
    @Html.LabelFor(model => model.allBuildings.First().Address, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.Address, new { htmlAttributes = new { @class = "form-control", @id = "show_address" } })
        @Html.ValidationMessageFor(model => model.Address, "", new { @class = "text-danger" })
    </div>
</div


   This is my javascript for address autocomplete(I do the same for the other one):

                                ////function to load building addresses when page loads.
          function ChangeAddressForSelect() {

              //creating autocomplete for address
              $('#show_address')
                  .blur(
                    function () {
                        var keyEvent = $.Event("keydown");
                        keyEvent.keyCode = $.ui.keyCode.ENTER;
                        $(this).trigger(keyEvent);

                  //    })
                  .autocomplete({
                      //source: '/Renovations/GetAddressForEdit',
                      source: function (request, response) {
                          response($.ui.autocomplete.filter(listAddress, 
                                                      request.term));
                      },
                      minLength: 0,
                      scroll: true,
                      select: function (event, ui) {
                          //set tagids to save
                          //$("#hidden_apartblockID").val(ui.item.id);
                          //// Tags for display
                          //this.value = ui.item.value;

                          return false;
                      },
                      focus: function () { $(this).autocomplete("search"); return false; },


                  .blur(function () {

                      //$(this).autocomplete('enable');


                  });

What is the most effective way to use model data as a source for each autcomplete? Should I switch to ajax or will ajax sourced data slow the page load?

Jane Cohen
  • 89
  • 1
  • 12
  • creating an ajax endpoint as the source is a common pattern. It's unclear though what a timeout would have to do with this code, you're passing what is effectively a static array. Exactly which line of code is throwing the error? What's the stack trace? Have you set a delay on the autocomplete or something? That might use a timeout. I think we're lacking a bit of info. – ADyson Feb 27 '19 at 16:56
  • Thats my issue. The error is pointing to the default settimeout function in jqueryui script. I have not set any set timeout function anywhere!! – Jane Cohen Feb 27 '19 at 17:04
  • then you need to use the stack trace to figure out what caused it to be called. – ADyson Feb 27 '19 at 17:13
  • It's probably not a massive issue though, they're just debug-mode warnings. See https://stackoverflow.com/questions/41218507/violation-long-running-javascript-task-took-xx-ms – ADyson Feb 27 '19 at 17:14
  • I have tried and its using the settimeout function of jqueryui every time i enter a new term in the autocomplete. – Jane Cohen Feb 27 '19 at 17:15
  • should i ignore it or try to improve code – Jane Cohen Feb 27 '19 at 17:17
  • It's unlikely to be your code directly. But then again, I can't see your 90% of your code, so I can't be sure. – ADyson Feb 27 '19 at 17:17
  • You didn't answer my earlier question - did you set the `delay` option in the autocomplete? http://api.jqueryui.com/autocomplete/#option-delay . this would almost certainly set a timer. – ADyson Feb 27 '19 at 17:17
  • i have a few autocompletes on same page when loading, should i just use ajax requests for all of them or model data? – Jane Cohen Feb 27 '19 at 17:18
  • sorry, no i did not set the delay option – Jane Cohen Feb 27 '19 at 17:18
  • i have commented out my code until i was left with only the code that i have posted above and I am still getting this error! – Jane Cohen Feb 27 '19 at 17:20
  • ajax is just one pattern. If makes the source more dynamic because you can filter data server-side on-demand rather than pre-populating with a fixed list. It depends how big the possible set of results is. If it's a fairly small set (< 100 maybe) then your current approach is likely to be fine. – ADyson Feb 27 '19 at 17:21
  • "if its not my code directly, then where could it be from?" something in the jQueryUI code, something triggered by you typing in the box. That's a pretty crucial moment so I imagine it fires off all sorts of stuff when that event happens. – ADyson Feb 27 '19 at 17:22
  • I noticed now that every time i enter a term that allows for more than one option in the filtered list, it fires the settimeout function... what d i change in the jquery function? thank you!! – Jane Cohen Feb 27 '19 at 17:30
  • 1
    Please provide a Minimal, Complete, and Verifiable example: https://stackoverflow.com/help/mcve Your source array is not configured properly, it should contain a `label` and `value` pair not `id`. You mention you have a number of autocompletes, it is best to include the proper code in your example. Also with ASP it is sometimes helpful to show the resulting HTML for better context. – Twisty Feb 27 '19 at 17:37

1 Answers1

0

Here is an example that I hope will help.

$(function() {
  var listAddress = [{
    label: "Address 1",
    value: 1,
    id: 1
  }, {
    label: "Address 2",
    value: 2,
    id: 2
  }, {
    label: "Address 3",
    value: 3,
    id: 3
  }];

  function saveAddress(e) {
    var a = parseInt($("#address_id").val());
    if (isNaN(a)) {
      return;
    }
    // Post back to save selected Address ID
    return true;
  }

  $('#show_address').autocomplete({
    source: listAddress,
    minLength: 0,
    scroll: true,
    select: function(event, ui) {
      $("#address_id").val(ui.item.id);
      $(this).val(ui.item.label);
      // Trigger any other events or post backs
      return false;
    }
  }).focus(function() {
    $(this).autocomplete("search", "");
    return false;
  }).blur(saveAddress);
});
.hidden {
  opacity: .25;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<div class="form-group">
  <!--
  @Html.LabelFor(model => model.allBuildings.First().Address, htmlAttributes: new { @class = "control-label col-md-2" })
  -->
  <label class="control-label col-md-2">Address</label>
  <div class="col-md-10">
    <input type="text" id="show_address" class="form-control" />
    <input type="text" id="address_id" class="hidden form-control" />
    <!--
        @Html.EditorFor(model => model.Address, new { htmlAttributes = new { @class = "form-control", @id = "show_address" } })
        -->
  </div>
</div>

First, it would be best to address your Source structure. You can use id, yet Autocomplete is looking for an Array or an Array of specific objects.

An array of objects with label and value properties: [ { label: "Choice1", value: "value1" }, ... ]

You can add other properties if needed. If your data is simple I would just stick just label and value.

Next, for focus and blur, the way that you want to use them would be outside of the Autocomplete, bound to the events with the input field itself. For Focus in the Autocomplete, this is related to focus of the list items.

Triggered when focus is moved to an item (not selecting). The default action is to replace the text field's value with the value of the focused item, though only if the event was triggered by a keyboard interaction.

It also was not clear what you wanted to do. It looks like you wanted to post back the selected ID to update in your Database someplace. I would do this with $.post() or $.ajax(). I do more work with PHP than .NET, so I cannot speak to this much and your example code doesn't really show what you want to do.

Hope that helps/

Twisty
  • 30,304
  • 2
  • 26
  • 45
  • Thanks for your answer, but I would like to use data sent through model, not hard code it , how would that work with your example? – Jane Cohen Feb 27 '19 at 23:03
  • @JaneCohen If that is the case, then you can have .NET push the data into a JavaScript Variable or you can pull it via AJAX Get request. Maybe like this: https://stackoverflow.com/questions/3365551/asp-net-mvc-how-to-convert-view-model-into-json-object – Twisty Feb 28 '19 at 01:08
  • Thank you for your link its been very helpful. One More question, if I have a large amount of data to pass through, is ajax a better option? – Jane Cohen Feb 28 '19 at 09:10