Update: February 22nd 2023 – Autocomplete for categories is now implemented
Turbo provides the technology in a Ruby on Rails web application to interact more dynamically with users. How does this make it easier to enter the author of a quotation? There are many tutorials on the web for implementing Autocomplete, for example the YouTube video Ruby on Rails #60 Hotwire Turbo Streams Autocomplete Search by Yaroslav Shmarov. I had a little trouble adopting what I found into my real-world web application. But on the second try I was able to put the pieces together better, and that’s what I want to show here. Maybe it will help other beginners a little bit?
Author’s last name in zitat-service.de should be automatically extended if the input is unique and also be clickable from the list. The first implementation was done with an additional form for the author’s name, session variables to synchronize with the form of the other fields of the citation. This was not rails-like at all, error-prone and had the basic problem that when selecting from the list, the previously made entries were lost when clicking on the link.
The implementation is explained here in a simplified way. The complete source code and the possibility to set up a Docker test instance can be found at
Koen Handekyn’s comment in Syntax for returning multiple turbo streams is a helpful hint on how to trigger multiple turbo stream updates at the same time with one render call. Other pieces of the puzzle are:
quotation[author_id]
for the ID of the selected author ID Quotation.author_id
author
, in which the first letters of the author’s name are entered and in which the selected author is displayedoninput: "this.form.requestSubmit()"
div#authors_list
is filled with a list of up to ten authors found, or remains empty and disappears with itcreate()
und update()
methods in the QuotationsController use the :commit
parameter of the submit button to distinguish whether the request comes from submitting the entire form or from entering text in the author fieldquotation[author_id]
is set and the author
field is filled with name, firstname and description<li>
, the GET requests when clicking on a link call the controller method author_selected()
, which then also triggers the two updates as for a found exactly one authorHere the main section from QuotationsController.update()
:
if params[:commit]
logger.debug { "update() quotation #{@quotation.inspect}" }
if @quotation.update(quotation_params)
hint = 'The quote has been updated.'
# give hint, e.g. if author autocomplete field is not completed
hint << " The author „#{Author.find(@quotation.author_id).name}” was not changed." if @authors.count != 1
return redirect_to @quotation, notice: hint
else
render :edit, status: :unprocessable_entity
end
else
turbo_author(old_author_id)
turbo_category(nil, old_category_ids, Category.check(@quotation))
render turbo_stream: turbo_stream_do_actions
end
With this solution, session variables are no longer necessary. The selected author is in the hidden field with his ID. The code for creating and updating does not differ significantly. Clicking on a link in the list of found authors triggers a GET request. Only the two turbo frames parts are updated within the page, other form input stands remaining.
Meanwhile, the input of the categories has also received an autocomplete :)