diff --git a/src/components/NcDialog/NcDialog.vue b/src/components/NcDialog/NcDialog.vue index a0634efd07..a14acdb76b 100644 --- a/src/components/NcDialog/NcDialog.vue +++ b/src/components/NcDialog/NcDialog.vue @@ -76,6 +76,58 @@ export default { } ``` + +### Form example +It is also possible to use the dialog for small forms. +This can be used when asking for a password, a name or similar to have native form validation. + +To make the dialog a form the `is-form` prop needs to be set. +When using the form variant you can also pass buttons with `nativeType` prop to add a native `submit` button. + +Note that this is not possible if the dialog contains a navigation! + +```vue + + +``` @@ -224,6 +280,16 @@ export default defineComponent({ default: false, }, + /** + * Make the dialog wrapper a HTML form element. + * The buttons will be wrapped within the form so they can be used as submit / reset buttons. + * Please note that when using the property the `navigation` should not be used. + */ + isForm: { + type: Boolean, + default: false, + }, + /** * Declare if hiding the modal should be animated * @default false @@ -299,7 +365,7 @@ export default defineComponent({ }, }, - emits: ['closing', 'update:open'], + emits: ['closing', 'update:open', 'submit'], setup(props, { emit, slots }) { /** @@ -347,7 +413,33 @@ export default defineComponent({ }) /** - * If the underlaying modal is shown + * @type {import('vue').Ref} + */ + const dialogElement = ref() + /** + * The HTML element to use for the dialog wrapper - either form or plain div + */ + const dialogTagName = computed(() => props.isForm && !hasNavigation.value ? 'form' : 'div') + /** + * Listener to assign to the dialog element + * This only sets the `@submit` listener if the dialog element is a form + */ + const dialogListeners = computed(() => dialogTagName.value === 'form' + ? { + /** + * @param {SubmitEvent} event Form submit event + */ + submit(event) { + event.preventDefault() + /** Forwarded HTMLFormElement submit event (only if `is-form` is set) */ + emit('submit', event) + }, + } + : {}, + ) + + /** + * If the underlying modal is shown */ const showModal = ref(true) @@ -356,6 +448,10 @@ export default defineComponent({ * Handle clicking a dialog button -> should close */ const handleButtonClose = () => { + // Skip close if invalid dialog + if (dialogTagName.value === 'form' && !dialogElement.value.reportValidity()) { + return + } handleClosing() window.setTimeout(() => handleClosed(), 300) } @@ -400,6 +496,9 @@ export default defineComponent({ })) return { + dialogElement, + dialogListeners, + dialogTagName, handleButtonClose, handleClosing, handleClosed, diff --git a/src/components/NcDialogButton/NcDialogButton.vue b/src/components/NcDialogButton/NcDialogButton.vue index 9419e98712..a2cd246953 100644 --- a/src/components/NcDialogButton/NcDialogButton.vue +++ b/src/components/NcDialogButton/NcDialogButton.vue @@ -10,6 +10,7 @@ Dialog button component used by NcDialog in the actions slot to display the butt