Search code examples
javascriptdjangohtmx

htmx not working on newly added form in django inline_formset


I have a form for my Purchase Order in which the items are presented in tabular format using django inline_formset. Within the form of the inline_formset, a search icon is placed beside the product select-form such that when the user will click on it, a modal will popup providing a functionality to the user to be able to search a product. And when the user will click a product on the search page, the corresponding product select-form in the main PO form will be updated/changed with the searched product. There is also an "Add more items" button which will add new form to the inline_formset, thereby providing a functionality to the user to dynamically add more PO items (using javascript).

All the abovementioned features work fine except that in the newly added form, the search icon failed to execute the hx-get embedded within the icon, like so:

In pod_form.html,

td>
    <div class="input-group">
        {{ field }}{% if field.name == 'product' %}
        <i class="fa-solid fa-magnifying-glass ms-1 d-flex align-items-center fa-icon" 
            hx-get="{% url 'product_search_popup' %}" hx-target="#dialog"></i>
        {% endif %}
    </div>
    <!-- dispaly field errors if there's any -->
    {% for error in field.errors %}
    <span style="color: red">{{ error }}</span>
    {% endfor %}
</td>

this html fragment is embedded in the script of type text/html, like so:

<script type="text/html" id="pod-template">
    <tr id="pod-__prefix__">
        {% for fields in po_inlines.empty_form.hidden_fields %}
            {{ fields }}
        {% endfor %}
    
        {% for field in po_inlines.empty_form.visible_fields %}
            {% include 'purchases/partials/pod_form.html' %}
        {% endfor %}
    </tr>
</script>

with the javascript coded as such,

<script>
    // PO Detail Inline
    var btnAddMorePOitems = document.querySelector('#pod-add-more')
    // on click of pod-add-more button, add new form
    btnAddMorePOitems.addEventListener('click', (ev) => {
        ev.preventDefault();
        // get document objects
        let tbodyPOitems = document.querySelector('#po-items')
        let podTemplate = document.querySelector('#pod-template')
        let podTotalForms = document.querySelector('#id_pod-TOTAL_FORMS')

        // build-up the content
        let count = tbodyPOitems.children.length
        let tmplMarkup = podTemplate.innerHTML
        let compiledTmpl = tmplMarkup.replace(/__prefix__/g, count)

        // insert a new row of the table representing the PO detail inline
        let newRow = tbodyPOitems.insertRow(count)
        newRow.outerHTML = compiledTmpl
        // update the form count
        podTotalForms.setAttribute('value', count + 1)

        // TODO: product search icon on_click event of newly added form
        searchIcon = document.querySelector(`#pod-${count}`).querySelector('.fa-magnifying-glass');
        searchIcon.addEventListener('click', (ev) => {
            ev.preventDefault()
            toggleActiveSearchIcon(ev.currentTarget)
        })
    })

    // event handler for search icon on-click
    var searchIcons = document.querySelector('#po-items').querySelectorAll('.fa-magnifying-glass');
    searchIcons.forEach(el => {
        el.addEventListener('click', (ev) => {
            ev.preventDefault()
            toggleActiveSearchIcon(el)
        })
    })

    // FUNCTION Definition
    function toggleActiveSearchIcon(el) {
        // mark the search icon as active
        document.querySelector('i.fa-icon.active')?.classList.remove('active')
        el.classList.add('active')
        // mark the select-form as active, which will be used as the hx-target
        // in the product_search modal page
        document.querySelector('select.active')?.classList.remove('active')
        el.previousElementSibling.classList.add('active')
    }
</script>

In the browser inspector tool, I can verify that the attribute hx-get and hx-target are present within the search icon of the newly added form. I can also verify that the click event works as expected. But I have found out that the view corresponding to the url specified in the hx-get is not being executed. Any thoughts on this?

If you have encountered similar problem to this, please share your solution(s).

PS: 1. Same problem behavior when the hx-target attribute is removed or replaced. 2. Removing the hx-get attribute and replaced with an anchor tag triggers the view, and thus displaying the data on the page specified in the href.


Solution

  • For dynamically added html, you need to call htmx.process() so htmx can process the newly added content. See this So answer