From ae7c8b2b160307646adf90cd09a091effa549238 Mon Sep 17 00:00:00 2001 From: Falk Neumann Date: Thu, 3 Feb 2022 18:00:22 +0100 Subject: [PATCH] feat: scroll first invalid element into view (#733) * feat: scroll first invalid element into view * fix: hide this feature behind a config flag * docs: enable and document feature flag --- addon/components/validated-form.js | 10 ++++++++++ tests/dummy/app/snippets/config-features.js | 10 ++++++++++ tests/dummy/app/templates/docs/configuration.md | 7 +++++++ tests/dummy/config/environment.js | 3 +++ 4 files changed, 30 insertions(+) create mode 100644 tests/dummy/app/snippets/config-features.js diff --git a/addon/components/validated-form.js b/addon/components/validated-form.js index c086917f..68340e37 100644 --- a/addon/components/validated-form.js +++ b/addon/components/validated-form.js @@ -1,3 +1,4 @@ +import { getOwner } from "@ember/application"; import { action } from "@ember/object"; import { scheduleOnce } from "@ember/runloop"; import Component from "@glimmer/component"; @@ -14,6 +15,10 @@ export default class ValidatedFormComponent extends Component { constructor(...args) { super(...args); + this.config = + getOwner(this).resolveRegistration("config:environment")[ + "ember-validated-form" + ]; if (this.args.model && this.args.model.validate) { scheduleOnce("actions", this, "validateModel", this.args.model); @@ -44,6 +49,11 @@ export default class ValidatedFormComponent extends Component { await model.validate(); if (model.get("isInvalid")) { + if (this.config?.features?.scrollErrorIntoView && model.errors[0]?.key) { + document + .querySelector(`[name=${model.errors[0].key}]`) + ?.scrollIntoView(); + } this.runCallback(PROP_ON_INVALID_SUBMIT); } else { this.runCallback(PROP_ON_SUBMIT); diff --git a/tests/dummy/app/snippets/config-features.js b/tests/dummy/app/snippets/config-features.js new file mode 100644 index 00000000..6830de22 --- /dev/null +++ b/tests/dummy/app/snippets/config-features.js @@ -0,0 +1,10 @@ +var ENV = { + // ... + "ember-validated-form": { + theme: "bootstrap", + features: { + scrollErrorIntoView: true, + } + }, + // ... +}; diff --git a/tests/dummy/app/templates/docs/configuration.md b/tests/dummy/app/templates/docs/configuration.md index 13ca2b0d..4c720062 100644 --- a/tests/dummy/app/templates/docs/configuration.md +++ b/tests/dummy/app/templates/docs/configuration.md @@ -33,3 +33,10 @@ For instance: {{demo.snippet 'permanent-custom-hint-component-template.hbs' label='permanent-custom-hint.hbs'}} {{/docs-demo}} + +## Other features + +If you want to scroll the first invalid field into view, you can set the +`scrollErrorIntoView` property to `true` (default: false). + +{{docs-snippet name='config-features.js' title='config/environment.js'}} diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js index f1e4d423..8d2ac59e 100644 --- a/tests/dummy/config/environment.js +++ b/tests/dummy/config/environment.js @@ -12,6 +12,9 @@ module.exports = function (environment) { defaults: { hint: "permanent-custom-hint", }, + features: { + scrollErrorIntoView: false, + }, }, EmberENV: { FEATURES: {