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.
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 2 years, 4 months ago by
xerviami.
-
This reply was modified 2 years, 4 months ago by
xerviami.
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.)