Glossary Realtime Filter

I have got a glossary list showing and am trying to add a dropdown filter and keyword search. The list is being pulled from a HubDB. I am trying to make the dropdown (column from HubDb called ‘category2’ and keyword search both update the list in realtime rather than having to press a submit button. Would anyone be able to let me know how I would implement the filter? Thank you in advance for any help.

<!--
 templateType: page
 isAvailableForNewContent: true
 label: Glossary 2200A
-->
{% extends "./layouts/base.html" %}

{% block body %}

{% if dynamic_page_hubdb_row %}

<!-- Content Page -->
<h1>{{ dynamic_page_hubdb_row.hs_name }}</h1>
<p>{{dynamic_page_hubdb_row.description}}</p>
<!-------->

{% elif dynamic_page_hubdb_table_id %}

<!-- Hero -->
{% dnd_area "body_dnd_area" %}
 {% dnd_section
 background_image = {
 'backgroundPosition': 'MIDDLE_CENTER',
 'backgroundSize': 'cover',
 'imageUrl': 'https://www.dragndrop.com/bg-image.jpg'
 },
 max_width=1000,
 vertical_alignment='MIDDLE'
 %}
 {% dnd_module path='../modules/Hero' %}
 {% module_attribute "html"%}
 This is your main headline.
 Use this space to tell everyone about what you have to offer.
 {% end_module_attribute %}
 {% end_dnd_module %}
 {% end_dnd_section %}
{% end_dnd_area %}
<!-------->

<!-- A-Z Filter Buttons -->
<div class="a-z_filter">

 <div class="">

 </div>

 <div class="a-z_filter_outercontainer">
 <div class="a-z_label v1"><p><strong>Find terms by letter:</strong></p></div>
 <div class="a-z_filter_container">

 <div class="a-z_label v2"><p><strong>Find terms<br>by letter:</strong></p></div>

 {% set table = hubdb_table_rows(module.hubdb_id) %}
 {% set alphabet = ["3","A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] %}
 {% for letter in alphabet %} 
 <a class="a-z_button" href="#{{ letter }}">{{ letter }}</a>
 {% endfor %}

 </div>
 </div>
</div>
<!-------->

<!-- Dropdown and Search Box that will update the list in realtime with no need to press a submit button-->
<div>
 <form id="form_id" method="get" >
 {# Category2 filter #}
 <div>
 <h3>Keyword Filter:</h3>
 <select name="category2" form="form_id" onChange="this.form.submit()">
 <option value="show-all">Show All</option>
 dropdown list pulled from HuBdb category2 column
 </select>
 </div>
 {# Search filter #}
 <div>
 <input name="publication" type="text" id="search-by" class="autocomplete" value="" placeholder="Search by keyword">
 </div>
 </form>
</div>
<!-------->

<!-- A-Z Listing -->
{% set table = hubdb_table_rows(module.hubdb_id) %}
{% set alphabet = ["3","A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] %}

<div class="row-fluid a-z">

{% for letter in alphabet %}

<h3 id="{{ letter }}" class="letter">{{ letter }}</h3>

 <div class="set">

 <ul class="word">

 {% for row in hubdb_table_rows(dynamic_page_hubdb_table_id) %}
 {% if row.name is string_startingwith letter %}

 <li><a href="{{ request.path }}/{{ row.hs_path }}?hs_preview=AyQeGSab-190730271634">{{ row.name }}</a></li>

 {% endif %} 
 {% endfor %}

 </ul>

 </div>

{% endfor %}
</div>
<!-------->

{% endif %}

<!-- CTA Banner-->
{% global_partial path='./partials/footer-cta-banner.html' %}
<!-------->
{% endblock %}

Hi @Woodsy, I hope that you are well!

Thanks for asking the HubSpot Community!
I spotted these threads, not sure if that’s entirely similar to what you are looking for but it might be interesting for you to take a look:
- The solution from @alyssamwilie on this post “Passing HubDB Multi-selection select options into Module Field Choice option”
- The solution from @alyssamwilie on this post “Choice field / select a row from HubDB list within a custom module”
Also, I’d love to put you in touch with our Top Experts: Hi @jonchim, @matt_scott and @Stephanie-OG do you have suggestions to help @Woodsy, please?
Have a fantastic day and thanks so much in advance for your help!
Bérangère

Hi @Bérangère

Those links you shared are not quite right for what I’m after. I would be extremely gratefully to any other community members who maybe able to share their knowledge around this request.
Thank you again Bérangère for reaching out to me with those suggestions.

James

Hi @Woodsy, thanks for getting back to me!
I’d love to put you in touch with our Top Experts: Hi @sylvain_tirreau, @Anton and @zach_threadint do you have suggestions to help @Woodsy, please?
Have a lovely weekend and thanks so much in advance for your help!
Bérangère

You can first retrieve and display all rows when rendering the page by including “data-*” attributes on each row. This would look something like this:

<div>
 <h3>Filter by category:</h3>
 <select id="category-filter">
 <option value="show-all">Show all</option>
 {% set rows = hubdb_table_rows(module.hubdb_id) %}
 {% set categories = rows | map(attribute='category2') | unique %}
 {% for category in categories %}
 <option value="{{ category }}">{{ category }}</option>
 {% endfor %}
 </select>
</div>

<div>
 <h3>Search by keyword:</h3>
 <input type="text" id="keyword-search" placeholder="Enter keyword...">
</div>

<div class="row-fluid a-z">
 {% for letter in alphabet %}
 <h3 id="{{ letter }}" class="letter">{{ letter }}</h3>
 <ul class="word">
 {% for row in rows %}
 {% if row.name is string_startingwith letter %}
 <li 
 data-category="{{ row.category2 }}" 
 data-name="{{ row.name | lower }}">
 <a href="{{ request.path }}/{{ row.hs_path }}">{{ row.name }}</a>
 </li>
 {% endif %}
 {% endfor %}
 </ul>
 {% endfor %}
</div>

And you can do something like this in javascript&colon;

document.addEventListener('DOMContentLoaded', function() {
 const selectCategory = document.getElementById('category-filter');
 const inputKeyword = document.getElementById('keyword-search');
 const items = Array.from(document.querySelectorAll('.word li'));

 function filterList() {
 const chosenCategory = selectCategory.value;
 const keyword = inputKeyword.value.trim().toLowerCase();

 items.forEach(li => {
 const category = li.dataset.category;
 const name = li.dataset.name;
 const matchCategory = (chosenCategory === 'show-all' || category === chosenCategory);
 const matchKeyword = (keyword === '' || name.includes(keyword));
 li.style.display = (matchCategory && matchKeyword) ? '' : 'none';
 });
 }

 selectCategory.addEventListener('change', filterList);
 inputKeyword.addEventListener('input', filterList);
 });

This is untested. Adapt this to your code.

Hi @sylvain_tirreau

Thank you for taking the time to look over my code. I have implemented it and everything works perfectly.

Under the ‘show all’ there is a blank entry that when clicked on removes a number of the listing items which includes all of a and b.

I have tried a few diffent things to remove that line but I just can’t seem to remove it. Do you know the best way to remove this line?

Thanks

Hi,

Change:

{% for category in categories %}
 <option value="{{ category }}">{{ category }}</option>
{% endfor %}

By this:

{% for category in categories %}
 {% if category %}
 <option value="{{ category }}">{{ category }}</option>
 {% endif %}
{% endfor %}