# Componente
# Introducción
Este componente renderizará un input de tipo time picker. El mismo se compone de dos partes, una de renderizado y otra de lógica (IrTimePicker Bone), esta ultima será la encargada de el manejo de los datos.
# Uso
Es importante recalcar el nombre del componente IrTimePicker a nivel de código, ya que este deberá usarse para llamar al componente para renderizarlo, ya sea individualmente o en un IrForm.
# Ejemplo
# Propiedades
| Propiedad | Tipo | Default | Descripción |
| label | String | Define el label del campo. | |
| readonly | Boolean |
| El valor |
| value | Time | '' | Valor del campo. Con el siguiente formato: |
| required | Boolean |
| En valor |
| clearable | String | String que define el tooltip que se mostrará en el botón de limpiar el valor del campo. Solo se mostrará el botón si esta propiedad está valorizada. | |
| hint | Object | String |
| Genera un texto de ayuda para el componente, que podrá ser o no, clickeable para navegar a un link determinado Propiedad con estructura de objeto con los siguientes keys: En la propiedad En la propiedad En la propiedad En la propiedad Las clases aplicables para las filas de la tabla podrán encontrarse en Vuetify en los siguientes enlaces:
|
# Código fuente
<template>
<ir-time-picker-bone
v-bind="$attrs"
ref="timePickerBone"
:key="componentKey"
v-model="value"
@input="(e) => updateValue(e)"
>
<div
slot-scope="{
placeholder,
readonly,
rules,
hideDetails,
label,
comportamientos,
clearable,
comportamientosPositions,
id_resolver,
comportamientoEvents
}"
class="d-flex align-center"
style="width: 100%"
>
<v-menu
ref="menu"
v-model="menu"
:disabled="readonly"
:close-on-content-click="false"
transition="scale-transition"
offset-y
min-width="auto"
>
<template #activator="{ on: onMenu }">
<div style="width: 100%">
<ir-label
v-if="isOutlinedd"
:label="label"
:error="hasError"
:disabled="handledAttrs.disabled"
:readonly="readonly"
/>
<v-text-field
ref="irTimePickerRef"
type="time"
:rules="rules"
:hide-details="hideDetails"
:placeholder="placeholder"
:value="hourInFormat"
:label="isOutlinedd ? undefined : label"
v-bind="getFilteredProps()"
style="width: 100%"
:disabled="readonly || handledAttrs.disabled"
:class="readonly ? 'not-readonly-tf' : 'is-readonly-tf'"
data-cy="timeTextField"
@update:error="setError"
@blur="(e) => updateValue(e)"
@keydown.enter="(e) => updateValue(e)"
>
<template #append>
<v-tooltip
v-if="clearable && clearable != ''"
bottom
>
<template #activator="{ on: onClose }">
<v-icon
class="mr-2"
:disabled="readonly || handledAttrs.disabled"
v-on="onClose"
@click="clearValue"
>
mdi-close
</v-icon>
</template>
<span>{{ clearable }}</span>
</v-tooltip>
</template>
<template #message="{ message }">
<div
class="d-block mb-1"
v-html="message"
/>
</template>
<template
v-for="position in comportamientosPositions"
#[position]
>
<div
:key="'comportamientos-slot-' + position"
class="d-flex"
style="gap: 10px"
>
<template v-for="(comportamiento, i) in comportamientos">
<ir-comportamiento
v-if="isCompValid(comportamiento, position)"
:key="'comportamiento-' + position + '-' + i"
:value="value"
v-bind="comportamiento"
:current_id_resolver="id_resolver"
:father-component-name="timePickerComponentName"
v-on="comportamientoEvents"
/>
</template>
</div>
</template>
<template
v-if="readonly && !value"
#prepend-inner
>
<div class="pr-2">
<v-icon color="warning"> mdi-alert-circle </v-icon>
</div>
</template>
</v-text-field>
</div>
</template>
</v-menu>
</div>
</ir-time-picker-bone>
</template>
<script>
import IrTimePickerBone from './IrTimePickerBone.vue'
import { setHintTag } from '../../../helpers/hint'
import { isOutlined } from '../../../helpers/utils.js'
import focusAndScrollMixin from '../../../mixins/focusAndScroll'
import { filterProps } from '../../../helpers/filterProps'
import { ref, computed, onMounted, useAttrs } from 'vue'
import { timePickerComponentName } from '../../../constants'
import { normalizeProps } from '../../../helpers/propsGenerator'
const localProps = normalizeProps({
value: {
type: String,
default: '',
required: true
},
isFocused: {
type: Boolean,
default: false
},
hint: {
type: [String, Object],
default: ''
}
})
export default {
name: timePickerComponentName,
components: { IrTimePickerBone },
props: localProps,
setup(props, { emit, attrs: $attrs }) {
const irTimePickerRef = ref(null)
const otherProps = ref({ ...$attrs })
const hasError = ref(false)
const menu = ref(false)
const componentKey = ref(0)
const isOutlinedd = computed(() => {
return isOutlined(handledAttrs.value.outlined)
})
const handledAttrs = computed(() => {
const hint = setHintTag(otherProps.value, props.hint)
let aux = { ...otherProps.value, ...$attrs }
delete aux.hint
if (hint) {
aux = { ...aux, hint }
}
delete aux.readonly
delete aux.rules
delete aux.pattern
delete aux.required
delete aux.label
delete aux.value
delete aux.width
delete aux.clearable
return aux
})
onMounted(() => {
if (props.isFocused) {
const ref = irTimePickerRef.value.$el.querySelector('input')
focusAndScrollMixin.methods.focusAndScroll(ref)
}
})
const updateValue = (e) => {
const regex = /^([01]\d|2[0-3]):([0-5]\d)$/ // Se valida que cumpla con el formato hh:mm
if (!regex.test(e.target.value)) {
resetInput()
} else {
emitInput(e.target.value)
}
}
const hourInFormat = computed(() => {
if (props.value && props.value.length === 4) {
return `${props.value.slice(0, 2)}:${props.value.slice(2)}`
}
return props.value
})
const emitInput = (value) => {
if (value && value.includes(':')) {
const [hours, minutes] = value.split(':')
const formattedValue = hours.padStart(2, '0') + minutes.padStart(2, '0')
emit('input', formattedValue) // Emitir en formato HHmm
} else {
emit('input', value)
}
}
const resetInput = () => {
componentKey.value++
}
const isCompValid = (comp, pos) => {
if (pos) {
return (
(typeof comp.visible === 'undefined' || comp.visible) &&
comp.position === pos
)
}
return (
(typeof comp.visible === 'undefined' || comp.visible) &&
comp.position === 'append'
)
}
const getFilteredProps = () => {
let props = filterProps(irTimePickerRef.value, otherProps.value, ['data-cy'])
props = { ...props, clearable: typeof props.clearable === 'undefined' }
return props
}
const clearValue = () => {
emit('input', '')
}
const setError = (eventValue) => {
if (eventValue) {
hasError.value = eventValue
}
}
return {
irTimePickerRef,
otherProps,
hasError,
menu,
componentKey,
isOutlinedd,
handledAttrs,
updateValue,
hourInFormat,
resetInput,
emitInput,
isCompValid,
getFilteredProps,
clearValue,
setError
}
}
}
</script>
<style scoped lang="scss"></style>