• Resolved xerviami

    (@xerviami)


    Dear,

    I am trying to implement autocompletion in PODS forms via external JS libraries.

    For instance, this one: https://tarekraafat.github.io/autoComplete.js/#/

    This library works well for text input in pure html.

    I tried to adapt it to autocomplete PODS form fields but it does not work.

    For a title field, I saw (by inspecting my website code) that the used html id is “pods-form-ui-pods-field-name”.

    Nevertheless, I find it impossible to use it with my autocompletion JS code.

    The exactly same code works if I use a pure html input field:

    <input type="text" id="autocomplete_id" name="field_name">

    The browser console gives me the following error: “Uncaught TypeError: e is not a function”.

    Perhaps there are some subtilities in the interaction between PODS and autoComplete.js….

    Can you help me or have you a hint ?

    Thank you very much

    Kind regards

    Xerviami

    • This topic was modified 10 months, 4 weeks ago by xerviami.
    • This topic was modified 10 months, 4 weeks ago by xerviami.
Viewing 3 replies - 1 through 3 (of 3 total)
  • Plugin Contributor Scott Kingsley Clark

    (@sc0ttkclark)

    Can you provide a gist or code snippet of the script you use to run it on your side? Maybe that can give us a clue as to what might be going on here.

    Thread Starter xerviami

    (@xerviami)

    Dear Scott,

    Here are both cases in the same shortcode I call in a page:

    $mypod = pods( 'pod_type' );
    $fields = array( 'post_title');
    echo $mypod->form( $fields );
    
    // Autocomplete on an html input field -> works
    
        echo <<<EOT1
        <!DOCTYPE html>
        <html>
        <body>
        
        <input type="text" id="autocomplete_id" name="pods_field_name">
    
        <script src="https://cdn.jsdelivr.net/npm/@tarekraafat/[email protected]/dist/autoComplete.min.js"></script>    
        <script>
        document.addEventListener("DOMContentLoaded", function() {        
            const autoCompleteJS = new autoComplete({
                selector: "#autocomplete_id",
                placeHolder: "Search for Food...",
                data: {
                    src: ["Sauce - Thousand Island", "Wild Boar - Tenderloin", "Goat - Whole Cut"],
                    cache: true,
                },
                resultItem: {
                    highlight: true
                },
                events: {
                    input: {
                        selection: (event) => {
                            const selection = event.detail.selection.value;
                            autoCompleteJS.input.value = selection;
                        }
                    }
                }
            });
        });
        </script>
        
        </body>
        </html>
        EOT1;
    
    
    
    // Autocomplete on a pod form field -> I can't make it work
        echo <<<EOT2
        <!DOCTYPE html>
        <html>
        <body>
        <script src="https://cdn.jsdelivr.net/npm/@tarekraafat/[email protected]/dist/autoComplete.min.js"></script>    
    
        <script>
        document.addEventListener("DOMContentLoaded", function() {
            var titleInput = document.getElementById("pods-form-ui-pods-field-name");
            
            const autoCompleteJS = new autoComplete({
                selector: titleInput,
                placeHolder: "Search for Food...",
                data: {
                    src: ["Sauce - Thousand Island", "Wild Boar - Tenderloin", "Goat - Whole Cut"],
                    cache: true,
                },
                resultItem: {
                    highlight: true
                },
                events: {
                    input: {
                        selection: (event) => {
                            const selection = event.detail.selection.value;
                            autoCompleteJS.input.value = selection;
                        }
                    }
                }
            });
        });
        </script>
        
        </body>
        </html>
        EOT2;
    

    The only difference is the selector:

    <input type="text" id="autocomplete_id" name="pods_field_name">
    [...]
    selector: "#autocomplete_id",

    which becomes:

    var titleInput = document.getElementById("pods-form-ui-pods-field-name");
    [...]
    selector: titleInput,

    As I write these lines, I can see in the autoComplete.js website this: “Works on anything (<input>, <textarea> and contentEditable elements)”

    Could this be the core issue ? Is there any way to make it work together ?

    Thanks a lot !

    Xerviami

    • This reply was modified 10 months, 4 weeks ago by xerviami.
    • This reply was modified 10 months, 4 weeks ago by xerviami.
    Plugin Support Paul Clark

    (@pdclark)

    Hi @xerviami,

    The challenge you may be running into is that while <input>, <textarea> and contentEditable may seem like “anything” for most use cases, the Pods form is powered by React, which is a different kind of “thing”.

    Specifically, a form element managed by React has its state managed outside of the DOM — JavaScript via React will update and override the actual DOM element any time it is interacted with in any way. This can cause unexpected behavior from a traditional DOM event model, such as the element not yet existing on DOMReady (React uses CompenentDidMount), or the element losing attached events and custom libraries not managed by React. (Even if autocomplete.js attaches to a form element successfully, the next time React does anything with it, the element will be destroyed and recreated, losing custom events and behavior.)

    There are a couple ways around this:

    • For basic modifications, Pods provides a JavaScript API which, at a minimum, provides methods for setting the value of a field in a way that React will accept and maintain. See https://docs.pods.io/code/dfv-js-api/. With this approach, one could inject a custom field into the form or anywhere on the page, hide the Pods field, then update the hidden Pods field with Pods DFV whenever the custom autocomplete field selects a value. One might call this a “proxy” approach — a custom field is displayed to the user which sends changes in values to another field, which is hidden, e.g., with CSS.
    • For advanced modifications, see the JavaScript MutationObserver API. It provides extremely flexible methods for running custom behavior any time observed DOM elements change. For example, even if one cannot hook into React’s ComponentDidMount and various data lifecycle events, one can observe the DOM, attaching custom events any time React modifies an element, changing its display or behavior, etc. This is fairly complex, but overcomes nearly all obstacles and limitations related to content on the page which may be constantly changed by other libraries.

    So, in summary:

    • selector: "#pods-form-ui-pods-field-name", first is not working in the provided version because the ID is being passed without # at the beginning, but also likely because DOMReady is not sufficient to attach to elements managed by React. If you are working on a simple text field, it might work, but in most cases, one would have to monitor #pods-form-ui-pods-field-name with a MutationObserver and re-attach the autocomplete any time it is modified, if it is managed with React. (There are two things going on here: first, the provided code switches from “selector” to “ID”. Selector starts with #. ID does not. The second is that if React is managing the field, one needs an Observer or Proxy; not just DOMReady.)
    • The simplest solution will likely be to separate a custom HTML input, as you have working, from the built-in Pods form, then use https://docs.pods.io/code/dfv-js-api/ to update the Pods field value any time the HTML autocomplete value changes. (Attach to the change or blur events of the field, or a custom event such as input as you have listed from the autocomplete library, set the value with DFV, hide the default field with CSS.)
Viewing 3 replies - 1 through 3 (of 3 total)
  • The topic ‘Autocomplete via external JS libraries’ is closed to new replies.