F
Filament12mo ago
Shavik

Autofocus in a Modal

Is there anyway to get the autofocus to work on input fields in slideovers/modals? It currently doesn't focus the field when opening a modal or slideover but does work on the full page form.
5 Replies
Shavik
Shavik12mo ago
Hmm odd, now it doesn't appear to be working in the full page forms. Odd. Are there certain things that could cause ->autofocus() to not cause the form to be autofocused on loading? Hmm for what it's worth, autofocus="autofocus" does get added to the input fields. Odd that that it doesn't actually focus that field.. 🤔
awcodes
awcodes12mo ago
I think autofocus only works on page load. I have seen issues, even with LW2 though where autofocus doesn’t work.
Shavik
Shavik12mo ago
Is there a way you know of to use javascript to focus a Filament Input field? Like somewhat built into the framework?
awcodes
awcodes12mo ago
Not built in. I have used JS to autofocus the email field on the login page before. And just added it with a renderHook. Not very clean, but it works. This is also in v2. But same principle applies in v3.
if (in_array(request()->route()->getName(), [
'verification.notice',
'verification.verify',
'filament.auth.login',
'password.request',
'password.reset',
])) {
Filament::registerRenderHook(
'body.end',
fn (): string => new HtmlString('<script>window.addEventListener("load", function(e) {document.querySelector("input").focus();});</script>')
);
}
if (in_array(request()->route()->getName(), [
'verification.notice',
'verification.verify',
'filament.auth.login',
'password.request',
'password.reset',
])) {
Filament::registerRenderHook(
'body.end',
fn (): string => new HtmlString('<script>window.addEventListener("load", function(e) {document.querySelector("input").focus();});</script>')
);
}
Shavik
Shavik12mo ago
Hmm that maybe could work. Just looking for the various forms across the page, whether edit page or modal, to have the first field autofocused when it opens. Will try to play around with the render hooks Thanks Well this works... lol - Focuses the first input field on the page as well as a modal when it pops up. Need to do some rework to make it auto focus the first specified autofocus=autofocus input on the page.
FilamentView::registerRenderHook(
'panels::body.start',
fn(): string => new HtmlString(<<<HTML
<script>
window.addEventListener('load', function(e) {
document.querySelector('main .fi-input').focus()
})

let observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes) {
mutation.addedNodes.forEach(function(node) {
// Check if it has the x-ref attribute modalContainer
if (node.nodeType === 1 && node.matches('[x-ref=\'modalContainer\']')) {
setTimeout(function () {
node.querySelector('.fi-input').focus()
}, 100)
}
})
}
})
})

observer.observe(document.body, { childList: true, subtree: true })
</script>
HTML
)
);
FilamentView::registerRenderHook(
'panels::body.start',
fn(): string => new HtmlString(<<<HTML
<script>
window.addEventListener('load', function(e) {
document.querySelector('main .fi-input').focus()
})

let observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes) {
mutation.addedNodes.forEach(function(node) {
// Check if it has the x-ref attribute modalContainer
if (node.nodeType === 1 && node.matches('[x-ref=\'modalContainer\']')) {
setTimeout(function () {
node.querySelector('.fi-input').focus()
}, 100)
}
})
}
})
})

observer.observe(document.body, { childList: true, subtree: true })
</script>
HTML
)
);
Ohh! this works great!
FilamentView::registerRenderHook(
'panels::body.start',
fn(): string => new HtmlString(<<<HTML
<script>
function autoFocus(element) {
let input = element.querySelector("[autofocus='autofocus']");
if (input) {
setTimeout(function() {
input.focus();
}, 100);
}
}

window.addEventListener("load", function(e) {
autoFocus(document);

var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes) {
mutation.addedNodes.forEach(function(node) {
// Check if it's an Element node and has the x-ref attribute 'modalContainer'
if (node.nodeType === 1 && node.matches("[x-ref='modalContainer']")) {
autoFocus(node);
}
});
}
});
});

observer.observe(document.body, { childList: true, subtree: true });
});

</script>
HTML
)
);
FilamentView::registerRenderHook(
'panels::body.start',
fn(): string => new HtmlString(<<<HTML
<script>
function autoFocus(element) {
let input = element.querySelector("[autofocus='autofocus']");
if (input) {
setTimeout(function() {
input.focus();
}, 100);
}
}

window.addEventListener("load", function(e) {
autoFocus(document);

var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes) {
mutation.addedNodes.forEach(function(node) {
// Check if it's an Element node and has the x-ref attribute 'modalContainer'
if (node.nodeType === 1 && node.matches("[x-ref='modalContainer']")) {
autoFocus(node);
}
});
}
});
});

observer.observe(document.body, { childList: true, subtree: true });
});

</script>
HTML
)
);
This auto selects the first input element on the page (edit page OR modal (even the slideover)).