Search code examples
jqueryjquery-uijsviews

jsView jQuery UI widget autocomplete Custom data and display


I am initializing different jQuery UI autocomplete-widgets per jsviews-jqueryui-widgets API (https://www.jsviews.com/download/sample-tag-controls/jsviews-jqueryui-widgets.js), which is calling the jQuery UI autocomplete widget API. This works fine!

But I want to modify the custom data and display of the autocomplete widget (https://jqueryui.com/autocomplete/#custom-data).

I think, I need the implement a chaining method, but I don't know, how to implement it in the API of jsView.

jsView Template:

<script id="inputText" type="text/x-jsrender">
        <input type="text" data-link="{autocomplete value _source=~suggestionList}" />
</script>

Chaining method:

.autocomplete( "instance" )._renderItem = function( ul, item ) {
      return $( "<li>" )
        .append( "<div>" + item.label + "<br>" + item.desc + "</div>" )
        .appendTo( ul );
    };

Part of jsviews-jqueryui-widgets API

autocomplete: {
  baseTag: "widget",
  widgetName: "autocomplete",
  linkedElement: "*",
  elem: "input",
  setSize: true,
  options: function() {
    var tag = this;
    return {
      change: function(evt, ui) {
        if (ui.item) {
          tag.updateValue(ui.item.value);
          // If there is a selected item, update bound value on keydown.
          // (Alternatively can set trigger=false to update on change)
        }
      },
      select: function(evt, ui) {
        if (ui.item) {
          tag.updateValue(ui.item.value);
        }
      },
      focus: function(evt, ui) {
        return false;
      }
    };
  }
}

What is the best way to do that?

Thanks!


Solution

  • One approach would be to create a derived {^{myAutocomplete ...}} tag, which overrides the _renderItem method, and the focus and select options:

    $.views.tags("myAutocomplete", {
      baseTag: "autocomplete",
      onBind: function(tagCtx) {
        this.baseApply(arguments);
        var widget = this.widget;
        widget._renderItem = function( ul, item ) {
          return $( "<li>" )
            .append( "<div>" + item.label + "<br>" + item.desc + "</div>" )
            .appendTo( ul );
        };
        widget.options.focus = function( event, ui ) {
          this.value = ui.item.label;
          // Other rendering code?
          return false;
        };
        widget.options.select = function( event, ui ) {
          this.value = ui.item.label;
          // Other rendering code, such as:
          // $( "#project-description" ).html( ui.item.desc );
          return false;
        };
      }
    });
    

    You could choose to override just the _renderItem method, and optionally override the options on the the individual instances:

    $.views.tags("myAutocomplete", {
      baseTag: "autocomplete",
      onBind: function(tagCtx) {
        this.baseApply(arguments);
        var widget = this.widget;
        widget._renderItem = function( ul, item ) {
          return $( "<li>" )
            .append( "<div>" + item.label + "<br>" + item.desc + "</div>" )
            .appendTo( ul );
        };
      }
    });
    

    then:

    <input type="text"
     data-link="{myAutocomplete value _source=~suggestionList _focus=~focus _select=~select}" />
    

    or

    {^{myAutocomplete value _source=~suggestionList _focus=~focus _select=~select /}}
    

    See the JsViews documentation topic: Accessing widget options, events and methods.