I have a simply script that should load after appconnect is fully done.
Otherwise an input field in a repeat group is not in the DOM yet and this eventListener is not added to it.
How do I trigger my javascript when appconnect is loaded?
Something like
document.addEventListener("appconnect:ready", function () {
would be nice.
For reference, the script I have (the timeout is now to give appconnect time to load:
document.addEventListener("DOMContentLoaded", function () {
setTimeout(function () {
const numberInputs = document.querySelectorAll('input[type="number"]');
// User doesn't scroll page when scrolling on an input field
numberInputs.forEach(function (input) {
input.addEventListener("wheel", function (event) {
if (document.activeElement === input) {
event.stopPropagation();
}
});
});
}, 100);
});
I usually use the updated event of the repeat region to trigger something like this that needs to first be rendered. If that still presents issues, inside the updated event you can use a condition that compares the source recordset count with the number of items currently in the repeat and only run when they are equal.
I looked closer at what you're trying to do and I think there is a better and cleaner solution for you problem.
Instead of running a function and looping over all inputs you could add an onwheel event on the input itself. And change the event.stopPropagation() to return false;
The easiest way is the answer from @Mark_Jonkers by adding it directly on the input but I assume you have many inputs and don't want to have to add it to each element each time.
You can listen to the ready event of the app component like:
<body is="dmx-app" onready="runMyScript()">
The ready event is triggered after the components initial render is finished, it doesn't mean that all data is available since those are often loaded async. When your inputs are dynamically generated in a repeat and depend on data loaded from the server, you then probably better use the success event from the serverconnect which loads the data or the updated event from the repeater.
You could also create your own component for number inputs like:
// create our component
dmx.Component('input-number', {
// extend from form-element component (input)
extends: 'form-element',
init (node) {
// first call the original init from the form-element compnent
dmx.Component('form-element').prototype.init.call(this, node);
// add extra listeners to the node
node.addEventListener('wheel', event => {
if (document.activeElement === node) {
event.stopPropagation();
}
});
}
});
// we can create the component like <input type="text" is="dmx-input-number">
// or we map it directly to all number inputs
// inportant is that the key is prepended before the others else the standart input will bind
dmx.config.mapping = {
'input[type=number]': 'input-number',
...dmx.config.mapping
};
As you said I'm looking for a holistic solution for inputs on many pages. But I suppose I can keep my current code (which works for most inputs).
And then trigger the same code when that particular serverconnect has a success event.
The custom component is an interesting solution and I want to explore more of custom components the coming months so I greatly appreciate the example. Thanks!