diff --git a/app/assets/javascripts/discourse/app/components/d-modal.hbs b/app/assets/javascripts/discourse/app/components/d-modal.hbs
index c9c2f14611a..467813988db 100644
--- a/app/assets/javascripts/discourse/app/components/d-modal.hbs
+++ b/app/assets/javascripts/discourse/app/components/d-modal.hbs
@@ -5,7 +5,7 @@
@element={{this.modal.containerElement}}
@inline={{@inline}}
>
-
-
+
{{#unless @inline}}
{{/unless}}
diff --git a/app/assets/javascripts/discourse/app/components/d-modal.js b/app/assets/javascripts/discourse/app/components/d-modal.js
index 8afc0436043..c262a3b979a 100644
--- a/app/assets/javascripts/discourse/app/components/d-modal.js
+++ b/app/assets/javascripts/discourse/app/components/d-modal.js
@@ -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;
+ };
+ }
}
diff --git a/app/assets/javascripts/discourse/tests/integration/components/d-modal-test.js b/app/assets/javascripts/discourse/tests/integration/components/d-modal-test.js
index 0349fcca19e..3bb63656186 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/d-modal-test.js
+++ b/app/assets/javascripts/discourse/tests/integration/components/d-modal-test.js
@@ -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`
+
+ <:body>
+
+
+ <:footer>
+
+
+
+ `
+ );
+
+ assert.dom("form.d-modal").exists();
+ await click(".d-modal button[type=submit]");
+ assert.deepEqual(submittedFormData.get("name"), "John Doe");
+ });
});
diff --git a/plugins/styleguide/assets/javascripts/discourse/components/sections/organisms/modal.hbs b/plugins/styleguide/assets/javascripts/discourse/components/sections/organisms/modal.hbs
index a0cd9b54630..2da5d63612e 100644
--- a/plugins/styleguide/assets/javascripts/discourse/components/sections/organisms/modal.hbs
+++ b/plugins/styleguide/assets/javascripts/discourse/components/sections/organisms/modal.hbs
@@ -32,6 +32,15 @@
{{on "click" this.toggleDismissable}}
/>
+
+
+
diff --git a/plugins/styleguide/assets/javascripts/discourse/components/sections/organisms/modal.js b/plugins/styleguide/assets/javascripts/discourse/components/sections/organisms/modal.js
index 8f719f8a6bd..05374113e4e 100644
--- a/plugins/styleguide/assets/javascripts/discourse/components/sections/organisms/modal.js
+++ b/plugins/styleguide/assets/javascripts/discourse/components/sections/organisms/modal.js
@@ -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() {