DEV: Support rendering `<DModal>` as a `<form>` element (#22507)

This commit is contained in:
David Taylor 2023-07-10 10:28:45 +01:00 committed by GitHub
parent 7339be7952
commit 9a1a3906c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 3 deletions

View File

@ -5,7 +5,7 @@
@element={{this.modal.containerElement}}
@inline={{@inline}}
>
<div
<this.dynamicElement
class={{concat-class
"modal"
"d-modal"
@ -95,7 +95,7 @@
</div>
</div>
</div>
</div>
</this.dynamicElement>
{{#unless @inline}}
<div class="modal-backdrop"></div>
{{/unless}}

View File

@ -1,6 +1,7 @@
import Component from "@glimmer/component";
import ClassicComponent from "@ember/component";
import { action } from "@ember/object";
import { tracked } from "@glimmer/tracking";
import { cached, tracked } from "@glimmer/tracking";
import { inject as service } from "@ember/service";
export const CLOSE_INITIATED_BY_BUTTON = "initiatedByCloseButton";
@ -170,4 +171,18 @@ export default class DModal extends Component {
throw `@flashType must be one of ${FLASH_TYPES.join(", ")}`;
}
}
// Could be optimised to remove classic component once RFC389 is implemented
// https://rfcs.emberjs.com/id/0389-dynamic-tag-names
@cached
get dynamicElement() {
const tagName = this.args.tagName || "div";
if (!["div", "form"].includes(tagName)) {
throw `@tagName must be form or div`;
}
return class WrapperComponent extends ClassicComponent {
tagName = tagName;
};
}
}

View File

@ -86,4 +86,29 @@ module("Integration | Component | d-modal", function (hooks) {
assert.dom(".d-modal .modal-header").hasClass("my-header-class");
assert.dom(".d-modal .modal-body").hasClass("my-body-class");
});
test("as a form", async function (assert) {
let submittedFormData;
this.handleSubmit = (event) => {
event.preventDefault();
submittedFormData = new FormData(event.currentTarget);
};
await render(
hbs`
<DModal @inline={{true}} @tagName="form" {{on "submit" this.handleSubmit}}>
<:body>
<input type="text" name="name" value="John Doe" />
</:body>
<:footer>
<button type="submit">Submit</button>
</:footer>
</DModal>
`
);
assert.dom("form.d-modal").exists();
await click(".d-modal button[type=submit]");
assert.deepEqual(submittedFormData.get("name"), "John Doe");
});
});

View File

@ -32,6 +32,15 @@
{{on "click" this.toggleDismissable}}
/>
</Styleguide::Controls::Row>
<Styleguide::Controls::Row @name="@tagName">
<ComboBox
@value={{this.modalTagName}}
@content={{this.modalTagNames}}
@onChange={{fn (mut this.modalTagName)}}
@valueProperty={{null}}
@nameProperty={{null}}
/>
</Styleguide::Controls::Row>
<Styleguide::Controls::Row @name="@title">
<Input @value={{this.title}} />
</Styleguide::Controls::Row>

View File

@ -6,6 +6,7 @@ import I18n from "I18n";
export default class extends Component {
@tracked inline = true;
@tracked dismissable = true;
@tracked modalTagName = "div";
@tracked title = I18n.t("styleguide.sections.modal.header");
@tracked body = this.args.dummy.shortLorem;
@tracked subtitle = "";
@ -13,6 +14,7 @@ export default class extends Component {
@tracked flashType = "success";
flashTypes = ["success", "info", "warning", "error"];
modalTagNames = ["div", "form"];
@action
toggleInline() {