richfaces autocomplete component/behavior

Overal Description

Proposed to implement in two variants for different usages:

all names - draft ones - could be changed after discussions.

 

autocompleteBehavior(postponed till filnal release) - behavior which allows to add autocomplete capabilities to any input. (just "behavior" later in text )

autocomplete - component which provides input with autocompleteBehavior built-in and combo button in order to call suggestions without typing. (just "component" later in text)

 

For M1 proposed to create component variant(simplest for usage by end developer)

Common part

Page declarations samples

behavior

The behavior should be attached to inputs as usually:

 

<h:inputText>
     <rich:autocompleteBehavior autocompleteMethod="#{}"/>
</h:inputText>

or

<h:inputText>
     <rich:autocompleteBehavior autocompleteMethod="#{}"/>
</h:inputText>

or

<rich:autocompleteBehavior autocompleteMethod="#{}"/>
 
     <h:inputText/>
     <h:inputText/>
     <h:inputText/>
</rich:autocompleteBehavior/>

 

component

 

<rich:autocomplete value="#{}" autocompleteMethod="#{}"/> 

 

Providing data for autocomplete:

There should be two ways of providing autocomplete data:

 

1) definition of the method which should return the suggestions according to the prefix passed:

<rich:autocomplete value="..." automcompleteMethod="#{bean.suggestCountries}"/> 

2) providing the collection Objects using autocompletesList attribute:

<rich:autocomplete value="..." autocompleteList="#{bean.countries}"/> 

 

Note: them should be defined only in corresponding modes. List could be used only for client mode and method for ajax and cachedAjax.

Filtering data

in client mode there will be two options:

  • simple variant - we filtering using fetchValue using startWith check.
  • user defined - user provides name of JS function (by using filterFunction attribute which should define JS function name) which should accept current String prefix and item fetch value and return boolean value which defines if the item should be included in list or not. It will be called for every item in list to filter it.

For ajax mode we using the same but initial list returned by the user should not be changed and the steps above should be applied only when list cached and getting additionally filtered on the client.

Data Conversion

Two converters could be possible to be defined by the developer:

  • converter for object from suggestion list
  • converter for result value String.

Autocomplete modes

Suggestions should be possible to be performed just on the client or to be done via ajax.

 

mode attribute should be available for definition with ajax, cachedAjax and client values.

 

Decide when to start suggestions

minChars attribute should be defined with some int value and define after which count of characters (considering tokens!) start show autocomplete list.

 

Autofill Input

autofill attribute should be added to behavior and component both. If true - first available suggestion will be automatically inserted to input as for comboBox for 3.3.x (previous directInputSuggestions see at livedemo)

 

Selection on list show/update

selectFirst boolean attribute should be added (selectFirstOnUpdate from 3.3.x combo). If true - first available item from suggestions will be selected in list and pressing enter - will cause selection of that item. If false - should works like google suggestion - nothing selected and clicking enter should just process current string entered.

Caching autocomplete data in ajax mode(cachedAjax mode)

Data should be cached in ajax mode in next way:

  • The developer defines when to trigger autocomplete script(by using minChars attribute for example)
  • After request finally fired and he get some suggestions - further changes (which adds some characters to the first request prefix except tokens) should rise just client side filtering of the list. There is no need in further ajax calls.
  • if the user changed input and initial prefix changed - ajax request should be fired again and new data cached.

Ajax Mode

in ajax mode - cahcing not used and every keyup rises ajax request.

Popup list representation

Autocomplete component should allow to redefine markup by using nested components definitions.

 

So if the component simply defined as

 

<rich:autocomplete value="..." autocompleteList="#{bean.countries}"/> 

 

then the list should be represented as simple list of country Strings. If country - not String but some complex object - the list of Strings should be generated by calling Coverter on every Item.

 

If the component has nested markup declarations - var attribute should be used and the nested components should became Item representation in list. Also the list base markup itlself should be additionally defined using layout attribute:

Table markup

<rich:autocomplete attached="false" value="..." autocompleteMethod="#{bean.countries}" var="country" 
   layout="table"> 
   <rich:column>
      <h:outputText value="#{country.name}">
   <rich:column>
</rich:autocomplete>

or list markup (encoded with ul-li tags)
<rich:autocomplete attached="false" value="..." autocompleteMethod="#{bean.countries}" var="country"
   layout="list"> 
   <h:outputText value="#{country.code} " style="font-weight:bold"/>
   <h:outputText value="#{country.name}"/>
</rich:autocomplete>

or simple div-based list 

<rich:autocomplete attached="false" value="..." autocompleteMethod="#{bean.countries}" var="country"
   layout="div">  
      <h:outputText value="#{country.code} " style="font-weight:bold"/>
      <h:outputText value="#{country.name}"/>
</rich:autocomplete>

or h:panelGrid based usage - almost the same as table but columns(td's inserted around every child)
<rich:autocomplete attached="false" value="..." autocompleteMethod="#{bean.countries}" var="country"
   layout="grid">  
      <h:outputText value="#{country.code} " style="font-weight:bold"/>
      <h:outputText value="#{country.name}"/>
</rich:autocomplete>

 

when custom representation used - fetchValue should be pointed to propoerty which will be actually added to input when item choosen.

Tokens support

  • the component should support tokens feature. Symbols entered after the token symbol should be used as new prefix for autocomplete.
  • should be supported in both modes with static autocomplete list and with ajax autocompleteMethod.

Fetching data via ajax

  • Should be available only for the case when autocompleteMethod used. (?)
  • Pre-fetching of some default list on rendering should be available.

Suggestions paggination

  • datascroller support should be discussed  for the component. (current impl should care about this feature possibility in future)

 

autocomplete Component

 

Should be based on UIInput standard component

Additional properties and modes

enableManualInput should be done as for comboBox form 3.3.x. true value - will mean that component allows only selection from list and not allows typing in input.

showButton boolean attribute should be added and be true by default.

disabled attribute should be supported as for any input. (+ button should have disabled representation.)

Client Side Event handlers attributes

autocomplete component

All the next attribute should be supported

input and list

all the onkey* events (up, down, press)

all the onmouse* events (click, dblclick, down, up,..)

onchange

onblur

onfocus

all these attributes should be behavior events


ajax

onbegin

oncomplete

onbeforedomupdate

 

autocomplete behavior

only ajax attributes should be there :

oncomplete

onbeforedomupdate

Limitations

Inputs and comands inside the popup - not supported. Such support looks too complex and not native functionality for the component.

Obsolete

This section contains of requirements which were dropped after review. Them could be revised later.

Additional object properties storing support

The main reasons to put this in obsolete - 3.3.x solution looks not very convenient, has known issues (objects serialization) and in general - not native for Input component. So - let's continue discussion about splitting functionality between this Input component and some (post M2) select component which will have this feature as native(as will works with objects and not Strings)

Should works the same as in 3.3.x implementation except the one change which will made it much more user friendly:

  • as the component currently produces input on his own - we could store objects on our own without needance to write java script by the user. We will just create additional hidden field and process it using declaration at component like objectValue=#{bean.selectedObjects}, so it will store Array or List of Objects.
    • using behavior - seems we need to use previous way of providing the objects to some developer handler.