# Componente
# Introducción
Este componente renderizará un input de tipo numeric field. El mismo se compone de dos partes, una de renderizado y otra de lógica (IrNumericField Bone), esta ultima será la encargada de el manejo de los datos.
# Uso
Es importante recalcar el nombre del componente IrNumericField a nivel de código, ya que este deberá usarse para llamar al componente para renderizarlo, ya sea individiualmente o en un IrForm.
# Ejemplo
# Propiedades
| Propiedad | Tipo | Default | Descripción |
| readonly | Boolean |
| El valor |
| hint | String | `` | Establece un texto de ayuda para el campo. |
| value | Number | Numero ingresado en el componente. | |
| required | Boolean |
| En valor |
| pattern | String |
| Un String que defina una expresión regular que deberá cumplir el input para ser válido. En caso de no poderse enviar |
| max | Number | undefined | Número máximo que se puede ingresar. Al no estar setteada esta propiedad el límite es infinito. |
| min | Number | undefined | Número mínimo que se puede ingresar. Al no estar setteada esta propiedad el límite es infinito. |
| 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:
|
| mask | String | | Determina un formato que cumplirá el texto introducido en el campo. Por ejemplo siendo mask = "999-999" el valor ingresado se forzará a ser algo como 333-333. El patron se define con los siguientes 3 caracteres: 9 para números, A para letras y S para alfanuméricos. El resto de los caracteres ingresados será tomado como tal. |
| money | Object | | Determina un formato que cumplirá el valor introducido en el campo. Este formato será definido por: |
# Código fuente
<template>
<ir-numeric-field-bone
v-bind="$attrs"
:value="value"
@input="handleInputIRT"
>
<div
slot-scope="{
inputEvents,
placeholder,
readonly,
rules,
hideDetails,
label,
comportamientos,
comportamientosPositions,
comportamientoEvents,
id_resolver,
maskHandler
}"
class="input-group js-parent-focus tw-w-full"
>
<ir-label
v-if="isOutlined"
:label="label"
:error="hasError"
:disabled="handledAttrs.disabled"
:readonly="readonly"
/>
<v-text-field
:ref="irNumericFieldRef"
:value="value"
type="number"
name="number"
class="pt-0 align-center"
:label="isOutlined ? undefined : label"
v-bind="getFilteredProps"
:placeholder="placeholder"
:hide-details="hideDetails"
:rules="rules"
:readonly="readonly"
:disabled="readonly || handledAttrs.disabled"
@input="(e)=>{ handleInputIRT(e), maskHandler(e, $refs[irNumericFieldRef]) }"
@update:error="setError"
@blur="handleInput"
v-on="inputEvents"
>
<template #message="{ message, key }">
<div v-html="message" />
</template>
<template
v-for="(position, k) in comportamientosPositions"
#[position]
>
<div
:key="'slot-comportamientos-numeric-' + k"
class="d-flex align-center"
style="gap: 10px"
>
<template v-for="(comportamiento, i) in comportamientos">
<ir-comportamiento
v-if="
(typeof comportamiento.visible === 'undefined' ||
comportamiento.visible) &&
comportamiento.position === position
"
:key="'comportamiento-numericfield-' + i"
:father_component_name="numericFieldComponentName"
:current_id_resolver="id_resolver"
v-bind="comportamiento"
:value="value"
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>
</ir-numeric-field-bone>
</template>
<script>
import IrNumericFieldBone from './IrNumericFieldBone.vue'
import { numericFieldComponentName } from '../../../constants'
import { setHintTag } from '../../../helpers/hint'
import focusAndScrollMixin from '../../../mixins/focusAndScroll'
import { isOutlined } from '../../../helpers/utils.js'
import { filterProps } from '../../../helpers/filterProps'
export default {
name: numericFieldComponentName,
components: {
IrNumericFieldBone
},
mixins: [focusAndScrollMixin],
inheritAttrs: false,
props: {
value: {
type: undefined, //Indefinido por caso en que se borre el contenido del input, se maneja en vuetify como "", rompería el type number
default: 0,
required: true
},
isFocused: {
type: Boolean,
default: false
},
hint: {
type: [String, Object],
default: ''
}
},
data() {
return {
irNumericFieldRef: numericFieldComponentName,
otherProps: {},
numericFieldComponentName: numericFieldComponentName,
hasError: false
}
},
computed: {
getFilteredProps() {
return filterProps(this.$refs[this.irNumericFieldRef], this.handledAttrs, [
'data-cy',
'max',
'min'
])
},
isOutlined() {
return isOutlined(this.handledAttrs.outlined)
},
handledAttrs() {
const hint = setHintTag(this.otherProps, this.hint)
let aux = { ...this.otherProps, ...this.$attrs }
delete aux.hint
if (hint) {
aux = { ...aux, hint }
}
delete aux.placeholder
delete aux.readonly
delete aux.rules
delete aux.pattern
delete aux.label
delete aux.value
delete aux.type
delete aux.name
return aux
}
},
mounted() {
if (this.isFocused) {
let element =
this.$refs[this.irNumericFieldRef].$el.querySelector('input')
this.focusAndScroll(element)
}
this.otherProps = { ...this.$attrs }
},
methods: {
setError(eventValue) {
this.hasError = eventValue
},
/**
* Handles the input event.
*
* @param {number|string} newValue - The new value to be handled.
*/
handleInputIRT(newValue) {
const minValue = this.$attrs.min
const isPositive = minValue >= 0
this.updateValue(newValue, isPositive && newValue < 0)
},
/**
* Handles the input event.
*
* @param {Event} newValue - The new value to be handled.
*/
handleInput(newValue) {
const minValue = this.$attrs.min
let newLocalValue = newValue.target.value
this.updateValue(newLocalValue, newLocalValue < minValue)
},
/**
* Updates the component's value with validation.
*
* @param {number|string} newLocalValue - The new value to be updated.
* @param {boolean} validationLocal - The validation result indicating if the new value is valid.
*/
updateValue(newLocalValue, validationLocal) {
if (isNaN(newLocalValue)) {
this.$emit('input', this.value)
return
}
if (newLocalValue !== this.value) {
const minValue = this.$attrs.min
const maxValue = this.$attrs.max
const value = isNaN(parseFloat(newLocalValue)) ? '' : parseFloat(newLocalValue)
const isHigher = value > maxValue
if (maxValue !== undefined && isHigher) {
this.$emit('input', maxValue)
return
}
if (minValue !== undefined && validationLocal) {
this.$emit('input', minValue)
return
}
this.$emit('input', value)
}
}
}
}
</script>
<style scoped>
.btn-reg {
border-bottom-left-radius: 0 !important;
border-top-left-radius: 0 !important;
}
</style>