Onkar Mehra
Onkar Mehra

Reputation: 83

Adding autofill/autocomplete suggestion to text input in python

I have tried several ways to add autocomplete/autofill suggestion functionality on text input. I have set a list 'names' for which I want autofill suggestions when being searched.

I tried this code which I got from pypi.org (https://pypi.org/project/fast-autocomplete/). It has library named fast-autocomplete. I tried using it but the problem I am facing here is that it is not giving me real-time autocomplete suggestions.

from fast_autocomplete import AutoComplete
words = {'book': {}, 'burrito': {}, 'pizza': {}, 'pasta':{}}
autocomplete = AutoComplete(words=words)

autocomplete.search(input('Type the word \n'), max_cost=3, size=3)

The output coming, is that when I type in the input, it is not giving me realtime suggestions. Once I have entered the word, then it is displaying the suggestions. I want the suggestions to be displayed realtime based on list like just how Google works.

enter image description here

enter image description here

This is the second example for the same- enter image description here

enter image description here

I have tried this. I want the suggestions to be displayed on the input text. Kindly help me.

Upvotes: 1

Views: 4508

Answers (1)

furas
furas

Reputation: 142651

input() sends text to search() only when you click Enter and I don't know if you can change it

But using widget.Text I could assign function which is executed always when there is new text in widget. To display result I use widget.Label but you could try to use Combobox

Doc: Widget List — Jupyter Widgets 8.0.2 documentation

import ipywidgets

from fast_autocomplete import AutoComplete

words = {'book': {}, 'burrito': {}, 'pizza': {}, 'pasta':{}}
autocomplete = AutoComplete(words=words)

def on_change(data):
    #print(data)
    
    text = data['new']
    #print(text)
    
    values = autocomplete.search(text, max_cost=3, size=3)
    #print(values)
    
    # convert nested list to string
    #values = ', '.join(sorted(set(str(item) for sublist in values for item in sublist)))

    values = str(values)
    #print(values)
    
    label.value = values
    
label = widgets.Label()

text = ipywidgets.Text(
    value='',
    placeholder='Type something',
    description='String:',
    disabled=False
)
text.observe(on_change, names='value')

display(text, label)

BTW:

on page with jupyter-widgets I found
adding autocompletion for Text? · Issue #692 · jupyter-widgets/ipywidgets
but it seems they still didn't create it.


EDIT:

Version which uses Combobox instead of Text+Label.

It can more useful because you can select value from list - but I see it doesn't clear list in HTML so later it can display the same value few times. Some workaround is to clear it with JavaScript but it could be better to use ID instead of tag datalist but I didn't find ID in python code.

EDIT: I added Button and on_click() in code.

import ipywidgets as widgets
from IPython.display import Javascript, display

from fast_autocomplete import AutoComplete

words = {'book': {}, 'burrito': {}, 'pizza': {}, 'pasta':{}}
autocomplete = AutoComplete(words=words)

def on_change(data):
    global text  # inform function to use global `text` instead of local `text` when you assign `text = ...`
    
    #print(data)

    text = data['new']
    #print(text)

    values = autocomplete.search(text, max_cost=3, size=3)
    #print(values)
    
    # convert nested list to flat list
    values = list(sorted(set(str(item) for sublist in values for item in sublist)))
    #print(values)
        
    # remove previous options from tag `<datalist>` in HTML
    display(Javascript(""" document.querySelector("datalist").innerHTML = "" """))
    
    combo.options = values
    
combo = widgets.Combobox(
    value='',
    placeholder='Type something',
    description='String:',
    disabled=False
)
combo.observe(on_change, names='value')

def your_function(widget):
    print('widget:', widget)
    print('global text:', text)
    # here make all calculations
    
button = widgets.Button(description='OK')
button.on_click(your_function)

display(combo, button)

enter image description here

Upvotes: 2

Related Questions