From ff475033aa3b3037a5be1fe0b9842b9e55ca88d0 Mon Sep 17 00:00:00 2001 From: simonihmig Date: Wed, 25 May 2022 13:20:52 +0200 Subject: [PATCH] Add form element to arguments passed to validate hook See https://github.com/kaliber5/ember-bootstrap/issues/1792 --- addon/components/bs-form.hbs | 1 + addon/components/bs-form.js | 13 ++++- tests/integration/components/bs-form-test.js | 58 ++++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/addon/components/bs-form.hbs b/addon/components/bs-form.hbs index 971a387e9..f36b40182 100644 --- a/addon/components/bs-form.hbs +++ b/addon/components/bs-form.hbs @@ -5,6 +5,7 @@ ...attributes {{on "keypress" this.handleKeyPress}} {{on "submit" this.handleSubmit}} + {{create-ref "formElement"}} > {{yield (hash diff --git a/addon/components/bs-form.js b/addon/components/bs-form.js index 5f453f200..2141e5705 100644 --- a/addon/components/bs-form.js +++ b/addon/components/bs-form.js @@ -9,6 +9,7 @@ import deprecateSubclassing from 'ember-bootstrap/utils/deprecate-subclassing'; import arg from '../utils/decorators/arg'; import { tracked } from '@glimmer/tracking'; import { cached } from 'tracked-toolbox'; +import { ref } from 'ember-ref-bucket'; /** Render a form with the appropriate Bootstrap layout class (see `formLayout`). @@ -118,6 +119,13 @@ import { cached } from 'tracked-toolbox'; */ @deprecateSubclassing export default class Form extends Component { + /** + * @property _element + * @type null | HTMLFormElement + * @private + */ + @ref('formElement') _element = null; + /** * Bootstrap form class name (computed) * @@ -332,10 +340,11 @@ export default class Form extends Component { * * @method validate * @param {Object} model + * @param {HTMLFormElement} form * @return {Promise} * @public */ - validate(model) {} // eslint-disable-line no-unused-vars + validate(model, form) {} // eslint-disable-line no-unused-vars /** * @property showAllValidations @@ -400,7 +409,7 @@ export default class Form extends Component { return RSVP.resolve() .then(() => { - return this.hasValidator ? this.validate(model) : null; + return this.hasValidator ? this.validate(model, this._element) : null; }) .then( (record) => { diff --git a/tests/integration/components/bs-form-test.js b/tests/integration/components/bs-form-test.js index f73feb797..65bfd5e71 100644 --- a/tests/integration/components/bs-form-test.js +++ b/tests/integration/components/bs-form-test.js @@ -152,6 +152,64 @@ module('Integration | Component | bs-form', function (hooks) { assert.verifySteps(['bubbles']); }); + test('form that supports validation calls validate hook when submitting', async function (assert) { + let model = {}; + this.set('model', model); + + class ValidatingForm extends Form { + '__ember-bootstrap_subclass' = true; + + get hasValidator() { + return true; + } + + async validate(modelArg, formArg) { + assert.step('validate'); + assert.strictEqual(modelArg, model, 'validate is called with model argument'); + assert.ok(formArg instanceof HTMLFormElement, 'validate is called with form argument'); + } + } + + this.set('form', ensureSafeComponent(ValidatingForm, this)); + + await render(hbs` + Test + `); + await triggerEvent('form', 'submit'); + + assert.verifySteps(['validate'], 'validate has been called'); + }); + + test('form that supports validation calls validate hook when calling submit action', async function (assert) { + let model = {}; + this.set('model', model); + + class ValidatingForm extends Form { + '__ember-bootstrap_subclass' = true; + + get hasValidator() { + return true; + } + + async validate(modelArg, formArg) { + assert.step('validate'); + assert.strictEqual(modelArg, model, 'validate is called with model argument'); + assert.ok(formArg instanceof HTMLFormElement, 'validate is called with form argument'); + } + } + + this.set('form', ensureSafeComponent(ValidatingForm, this)); + + await render(hbs` + + + + `); + await click('button'); + + assert.verifySteps(['validate'], 'validate has been called'); + }); + test('Submitting the form with valid validation calls onBeforeSubmit and onSubmit action', async function (assert) { let submit = sinon.spy(); let before = sinon.spy();