vue-formulate
vue-formulate copied to clipboard
Scroll user to first form error @submit
Describe the new feature you'd like
I'd love to see an option to scroll users to the first error input (if an error exists) when they submit a form. Also would like to optionally focus the input that has the error.
Looking at the docs, it looks like this can be done with some kind of custom form error handler, but it would really be appreciated if we could simply set an option like the following:
<FormulateForm
:scroll-to-error="true"
:focus-error="true"
>
This was also mentioned in issues #182
If you have a temporary solution to accomplish this, I imagine many others would benefit from it as well.
Sounds like perfect plugin territory to me. Do you have any interest in tackling one yourself?
@titusdecali Nice feature request.
I also needed this feature in a project I was working on and I was able to accomplish this behavior after checking the hasValidationErrors
result from a function triggered by @submit.raw
as in the following example.
https://codepen.io/acemir/pen/LYZbozN
This approach has a downside because Element.scrollIntoView
with the center option is not widely supported but a polyfill like scroll-into-view or scroll-behavior-polyfill can be used to overcome this limitation.
Either way it would be great to see this as a ready-to-use feature or as a plugin.
I was able to accomplish this behavior after checking the
hasValidationErrors
result from a function triggered by@submit.raw
as in the following example.https://codepen.io/acemir/pen/LYZbozN
You are the man @acemir ! Your solution was perfect for my needs and came right on time to finish a client's project. Can't thank you enough.
I think simply documenting this method is enough for most use cases. @justin-schroeder what do you think about adding it in the docs?
This is right on the edge of what I think the library should do. On one hand, it makes it much easier to use, and we're all about being "the easiest way to build forms with vue". On the other hand, it starts making assumptions about how the form is laid out, and that fields are even on the currently visible screen (as opposed to in a tab) etc. I'm on the fence haha. Someone push me one way or another and I'll go for it.
While @acemir's solution works perfectly, it's not something directly provided for in the package and thus adding it to the docs might be a bit strange, and I can fully understand that. But, I think this feature is common enough in more complex forms that devs will definitely appreciate having the option of it.
I'd really love to see it on the roadmap.
After more thought I agree this would be a great feature — although I think it falls pretty squarely in "plugin" territory. However, the plugin ecosystem for vue formulate doesn't really exist yet, so I created a new project board called "Plugins" where we can stash good plugin ideas for the community to build out or the maintainers of the project. So we'll keep this open and "kind of" on the road map.
I've been dreaming up lots of ways to kickstart that plugin ecosystem, so more on that to come.
Thanks @acemir your solution was helpful. For those my want to make it reusable. following is how I am using it as a global method.
<FormulateForm
@submit-raw="$global.handleFormulateSubmit($event, submit)" >
// Usage
// Global Method - make sure 2nd Parameter the function you want to call on successful submittion.
const handleFormulateSubmit = (submitResult, submit) => {
submitResult.hasValidationErrors().then((hasErrors) => {
if (hasErrors) {
scrollToError(submitResult.form.$el);
} else {
submitResult.values().then((data) => {
submit();
});
}
});
};
const scrollToError = ($formEl) => {
const errorWrapperEl = $formEl.querySelector('[data-has-errors="true"]');
const errorWrapperInput = errorWrapperEl && errorWrapperEl.querySelector("input,select,textarea");
if (errorWrapperInput) {
errorWrapperInput.focus();
errorWrapperInput.scrollIntoView({ block: "center" });
}
};
Vue.prototype.$global = {
handleFormulateSubmit,
};
You may also use Mixin or Composable (vue 2.7) but I had hundreds of forms so a global method made more sense.