Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/docs-next/components/Autocomplete.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ title: Autocomplete
| blur | |
| focus | |
| update:modelValue | |
| invalid | |
| select | **selected** `Object` - selected option<br/>**event** `Event` - native event |
| infinite-scroll | |
| typing | |
Expand Down
1 change: 1 addition & 0 deletions packages/docs-next/components/Datepicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ title: Datepicker
| range-end | |
| blur | |
| focus | |
| invalid | |
| update:modelValue | |
| change-month | |
| change-year | |
Expand Down
1 change: 1 addition & 0 deletions packages/docs-next/components/Datetimepicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ title: Datetimepicker
| change-year | |
| blur | |
| focus | |
| invalid | |
| update:modelValue | |

## Slots
Expand Down
1 change: 1 addition & 0 deletions packages/docs-next/components/Input.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ title: Input
| ----------------- | ---------- | ----------- |
| blur | |
| focus | |
| invalid | |
| update:modelValue | |
| icon-click | |
| icon-right-click | |
Expand Down
1 change: 1 addition & 0 deletions packages/docs-next/components/Inputitems.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ title: Inputitems
| icon-right-click | |
| blur | |
| focus | |
| invalid | |
| update:modelValue | |
| add | |
| remove | |
Expand Down
1 change: 1 addition & 0 deletions packages/docs-next/components/Select.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ title: Select
| ----------------- | ---------- | ----------- |
| blur | |
| focus | |
| invalid | |
| update:modelValue | |

## Slots
Expand Down
1 change: 1 addition & 0 deletions packages/docs-next/components/Timepicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ title: Timepicker
| ----------------- | ---------- | ----------- |
| blur | |
| focus | |
| invalid | |
| update:modelValue | |

## Slots
Expand Down
13 changes: 7 additions & 6 deletions packages/docs-next/documentation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -523,12 +523,13 @@ Take a look at the [official TailwindCSS + Oruga example](https://github.com/oru

## Global Props

| Field | Description | Default |
| ------------------ | ------------------------------------------------------------- | ------- |
| statusIcon | Show status icon using field and variant prop | true |
| statusVariantIcon | Default mapping of variant and icon name | <code style='white-space: nowrap; padding: 0;'>{<br>&nbsp;&nbsp;'success': 'check',<br>&nbsp;&nbsp;'danger': 'alert-circle',<br>&nbsp;&nbsp;'info':'information', <br>&nbsp;&nbsp;'warning': 'alert'<br>} </code> |
| useHtml5Validation | Default form components use-html5-validation attribute | true |
| iconPack | Icon pack used internally and on the Icon component attribute | 'mdi' |
| Field | Description | Default |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| statusIcon | Show status icon using field and variant prop | true |
| statusVariantIcon | Default mapping of variant and icon name | <code style='white-space: nowrap; padding: 0;'>{<br>&nbsp;&nbsp;'success': 'check',<br>&nbsp;&nbsp;'danger': 'alert-circle',<br>&nbsp;&nbsp;'info':'information', <br>&nbsp;&nbsp;'warning': 'alert'<br>} </code> |
| useHtml5Validation | Default form components use-html5-validation attribute | true |
| iconPack | Icon pack used internally and on the Icon component attribute | 'mdi' |
| reportInvalidInput | Callback function that allows for custom behavior when HTML constraint validation would visually report that a field is invalid. Takes the input and its parent field (if any) as arguments. | <code style='white-space: nowrap; padding: 0;'>null</code> |

Take a look at each component docs to know all customizable fields/props by config.

Expand Down
1 change: 1 addition & 0 deletions packages/docs/components/Autocomplete.md
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ export default {
| blur | |
| focus | |
| input | |
| invalid | |
| select | **selected** `Object` - selected option<br>**event** `Event` - native event |
| select-header | |
| select-footer | |
Expand Down
1 change: 1 addition & 0 deletions packages/docs/components/Datepicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,7 @@ export default {
| blur | |
| focus | |
| input | |
| invalid | |
| change-month | |
| change-year | |
| active-change | |
Expand Down
1 change: 1 addition & 0 deletions packages/docs/components/Datetimepicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ export default {
| blur | |
| focus | |
| input | |
| invalid | |

## Slots

Expand Down
1 change: 1 addition & 0 deletions packages/docs/components/Input.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ export default {
| blur | |
| focus | |
| input | |
| invalid | |

## Style

Expand Down
1 change: 1 addition & 0 deletions packages/docs/components/Inputitems.md
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ export default {
| blur | |
| focus | |
| input | |
| invalid | |
| add | |
| typing | |
| remove | |
Expand Down
1 change: 1 addition & 0 deletions packages/docs/components/Select.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ export default {
| blur | |
| focus | |
| input | |
| invalid | |

## Slots

Expand Down
1 change: 1 addition & 0 deletions packages/docs/components/Timepicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ export default {
| blur | |
| focus | |
| input | |
| invalid | |

## Slots

Expand Down
13 changes: 7 additions & 6 deletions packages/docs/documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -613,12 +613,13 @@ Take a look at the [official TailwindCSS + Oruga example](https://github.com/oru

## Global Props

| Field | Description | Default |
| ------------------ | ------------------------------------------------------------- | ------- |
| statusIcon | Show status icon using field and variant prop | true |
| statusVariantIcon | Default mapping of variant and icon name | <code style='white-space: nowrap; padding: 0;'>{<br>&nbsp;&nbsp;'success': 'check',<br>&nbsp;&nbsp;'danger': 'alert-circle',<br>&nbsp;&nbsp;'info':'information', <br>&nbsp;&nbsp;'warning': 'alert'<br>} </code> |
| useHtml5Validation | Default form components use-html5-validation attribute | true |
| iconPack | Icon pack used internally and on the Icon component attribute | 'mdi' |
| Field | Description | Default |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| statusIcon | Show status icon using field and variant prop | true |
| statusVariantIcon | Default mapping of variant and icon name | <code style='white-space: nowrap; padding: 0;'>{<br>&nbsp;&nbsp;'success': 'check',<br>&nbsp;&nbsp;'danger': 'alert-circle',<br>&nbsp;&nbsp;'info':'information', <br>&nbsp;&nbsp;'warning': 'alert'<br>} </code> |
| useHtml5Validation | Default form components use-html5-validation attribute | true |
| iconPack | Icon pack used internally and on the Icon component attribute | 'mdi' |
| reportInvalidInput | Callback function that allows for custom behavior when HTML constraint validation would visually report that a field is invalid. Takes the input and its parent field (if any) as arguments. | <code style='white-space: nowrap; padding: 0;'>null</code> |

Take a look at each component docs to know all customizable fields/props by config.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
@update:modelValue="onInput"
@focus="focused"
@blur="onBlur"
@invalid="onInvalid"
@keydown="keydown"
@keydown.up.prevent="keyArrows('up')"
@keydown.down.prevent="keyArrows('down')"
Expand Down Expand Up @@ -120,7 +121,7 @@ export default defineComponent({
},
mixins: [BaseComponentMixin, FormElementMixin],
inheritAttrs: false,
emits: ['update:modelValue', 'select', 'infinite-scroll', 'typing', 'focus', 'blur', 'icon-click', 'icon-right-click'],
emits: ['update:modelValue', 'select', 'infinite-scroll', 'typing', 'focus', 'blur', 'invalid', 'icon-click', 'icon-right-click'],
props: {
/** @model */
modelValue: [Number, String],
Expand Down
5 changes: 3 additions & 2 deletions packages/oruga-next/src/components/datepicker/Datepicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@
:use-html5-validation="false"
@change="onChangeNativePicker"
@focus="onFocus"
@blur="onBlur"/>
@blur="onBlur"
@invalid="onInvalid" />
</div>
</template>

Expand Down Expand Up @@ -331,7 +332,7 @@ export default defineComponent({
$datepicker: this
}
},
emits: ['update:modelValue', 'focus', 'blur', 'change-month', 'change-year', 'range-start', 'range-end', 'active-change', 'icon-right-click'],
emits: ['update:modelValue', 'focus', 'blur', 'invalid', 'change-month', 'change-year', 'range-start', 'range-end', 'active-change', 'icon-right-click'],
props: {
modelValue: {
type: [Date, Array]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@
:use-html5-validation="useHtml5Validation"
@change="onChangeNativePicker"
@focus="onFocus"
@blur="onBlur"/>
@blur="onBlur"
@invalid="onInvalid" />
</template>

<script lang="ts">
Expand Down Expand Up @@ -103,7 +104,7 @@ export default defineComponent({
configField: 'datetimepicker',
mixins: [FormElementMixin, BaseComponentMixin],
inheritAttrs: false,
emits: ['update:modelValue', 'change-year', 'change-month', 'icon-right-click', 'active-change'],
emits: ['update:modelValue', 'focus', 'blur', 'invalid', 'change-year', 'change-month', 'icon-right-click', 'active-change'],
props: {
modelValue: {
type: Date
Expand Down
6 changes: 4 additions & 2 deletions packages/oruga-next/src/components/input/Input.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
:value="computedValue"
@input="onInput"
@blur="onBlur"
@focus="onFocus">
@focus="onFocus"
@invalid="onInvalid" />

<textarea
v-else
Expand All @@ -23,6 +24,7 @@
@input="onInput"
@blur="onBlur"
@focus="onFocus"
@invalid="onInvalid"
:style="computedStyles"
/>

Expand Down Expand Up @@ -78,7 +80,7 @@ export default defineComponent({
mixins: [BaseComponentMixin, FormElementMixin],
configField: 'input',
inheritAttrs: false,
emits: ['update:modelValue', 'icon-click', 'icon-right-click'],
emits: ['update:modelValue', 'input', 'focus', 'blur', 'invalid', 'icon-click', 'icon-right-click'],
props: {
/** @model */
modelValue: [Number, String],
Expand Down
3 changes: 2 additions & 1 deletion packages/oruga-next/src/components/inputitems/Inputitems.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
@typing="onTyping"
@focus="onFocus"
@blur="customOnBlur"
@invalid="onInvalid"
@keydown="keydown"
@compositionstart="isComposing = true"
@compositionend="isComposing = false"
Expand Down Expand Up @@ -117,7 +118,7 @@ export default defineComponent({
mixins: [FormElementMixin, BaseComponentMixin],
inheritAttrs: false,
configField: 'inputitems',
emits: ['update:modelValue', 'focus', 'blur', 'add', 'remove', 'typing', 'infinite-scroll', 'icon-right-click'],
emits: ['update:modelValue', 'focus', 'blur', 'invalid', 'add', 'remove', 'typing', 'infinite-scroll', 'icon-right-click'],
props: {
/** @model */
modelValue: {
Expand Down
5 changes: 3 additions & 2 deletions packages/oruga-next/src/components/select/Select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
:multiple="multiple"
:size="nativeSize"
@blur="onBlur"
@focus="onFocus">
@focus="onFocus"
@invalid="onInvalid">

<template v-if="placeholder">
<option
Expand Down Expand Up @@ -64,7 +65,7 @@ export default defineComponent({
mixins: [BaseComponentMixin, FormElementMixin],
configField: 'select',
inheritAttrs: false,
emits: ['update:modelValue', 'focus', 'blur'],
emits: ['update:modelValue', 'focus', 'blur', 'invalid'],
props: {
/** @model */
modelValue: {
Expand Down
4 changes: 3 additions & 1 deletion packages/oruga-next/src/components/timepicker/Timepicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@
:use-html5-validation="useHtml5Validation"
@change="onChange($event.target.value)"
@focus="handleOnFocus"
@blur="onBlur() && checkHtml5Validity()"/>
@blur="onBlur"
@invalid="onInvalid" />
</div>
</template>

Expand Down Expand Up @@ -194,6 +195,7 @@ export default defineComponent({
}
}
},
emits: ['focus', 'blur', 'invalid'],
computed: {
inputBind() {
return {
Expand Down
63 changes: 62 additions & 1 deletion packages/oruga-next/src/utils/FormElementMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@ import { defineComponent } from 'vue'
import { getOptions } from './config';
import { getValueByPath } from './helpers'

// This should cover all types of HTML elements that have properties related to
// HTML constraint validation, e.g. .form and .validity.
const validatableFormElementTypes = typeof window === 'undefined' ? [] : [
HTMLButtonElement,
HTMLFieldSetElement,
HTMLInputElement,
HTMLObjectElement,
HTMLOutputElement,
HTMLSelectElement,
HTMLTextAreaElement,
];

type ValidatableFormElement = InstanceType<typeof validatableFormElementTypes[number]>;

function asValidatableFormElement(el: unknown): ValidatableFormElement | null {
if (validatableFormElementTypes.some(t => el instanceof t)) {
return el as ValidatableFormElement;
} else {
return null;
}
}

export default defineComponent({
inject: {
$field: { from: "$field", default: false }
Expand Down Expand Up @@ -129,6 +151,45 @@ export default defineComponent({
this.$emit("focus", event);
},

onInvalid(event: Event) {
this.checkHtml5Validity();
const validatable = asValidatableFormElement(event.target);
if (validatable && this.parentField && this.useHtml5Validation) {
// We provide our own error message on the field, so we should suppress the browser's default tooltip.
// We still want to focus the form's first invalid input, though.
event.preventDefault();
let isFirstInvalid = false;
if (validatable.form != null) {
const formElements = validatable.form.elements;
for (let i = 0; i < formElements.length; ++i) {
const element = asValidatableFormElement(formElements.item(i));
if (element && element.willValidate && !element.validity.valid) {
isFirstInvalid = (validatable === element);
break;
}
}
}
if (isFirstInvalid) {
const fieldElement = this.parentField.$el;
const invalidHandler = getValueByPath(getOptions(), 'reportInvalidInput');
if (invalidHandler instanceof Function) {
invalidHandler(validatable, fieldElement);
} else {
// We'll scroll to put the whole field in view, not just the element that triggered the event,
// which should mean that the message will be visible onscreen.
// scrollIntoViewIfNeeded() is a non-standard method (but a very common extension).
// If we can't use it, we'll just fall back to focusing the field.
const canScrollToField = fieldElement ? fieldElement.scrollIntoViewIfNeeded != undefined : false;
validatable.focus({ preventScroll: canScrollToField });
if (canScrollToField) {
fieldElement.scrollIntoViewIfNeeded();
}
}
}
}
this.$emit("invalid", event);
},

getElement() {
let el = this.$refs[this.$elementRef];
while (el && el.$elementRef) {
Expand Down Expand Up @@ -169,7 +230,7 @@ export default defineComponent({
const el = this.getElement();
if (!el) return;

if (!el.checkValidity()) {
if (!el.validity.valid) {
this.setInvalid();
this.isValid = false;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
@input="onInput"
@focus="focused"
@blur="onBlur"
@invalid="onInvalid"
@keydown.native="keydown"
@keydown.native.up.prevent="keyArrows('up')"
@keydown.native.down.prevent="keyArrows('down')"
Expand Down
3 changes: 2 additions & 1 deletion packages/oruga/src/components/datepicker/Datepicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@
:use-html5-validation="false"
@change.native="onChangeNativePicker"
@focus="onFocus"
@blur="onBlur"/>
@blur="onBlur"
@invalid="onInvalid" />
</div>
</template>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@
:use-html5-validation="useHtml5Validation"
@change.native="onChangeNativePicker"
@focus="onFocus"
@blur="onBlur"/>
@blur="onBlur"
@invalid="onInvalid" />
</template>

<script>
Expand Down
Loading