# Componente

# Introducción

Componente que mostrará un input de tipo radio group.

# Uso

Es importante recalcar el nombre del componente IrRadioGroup 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

false

El valor readonly = true, establecerá al campo como solo lectura.

required Boolean

false

En valor true, define que el componente debe ser valorizado para ser válido.

items-fcn String

''

Establece la función de base de datos a la cual se consultará para completar la información de la propiedad items. La consulta a la base de datos reemplazará lo contenido en la propiedad items, a menos que no se envíe la propiedad fcn o se envíe con el valor '', en dicho caso no se consultará a la BD y se utilizarán los datos provistos en items.

En caso de que la consulta a la BD devuelva un objeto con propiedades del IrRadioGroup, las mismas se utilizarán para reemplazar las propiedades actuales. Si únicamente devuelve un arreglo, el mismo se utilizará para reemplazar los items.

args-items-fcn Array

''

Establece los argumentos que recibirá la función provista en items-fcn

item-attrs Object

{}

Atributos que se pasaran a cada v-radio-button dentro del group. Dichas propiedades pueden verse aquí

items Array

[]

Array de objectos con la estructura:

[
  {
    text: String,
    value: Any type,
  }
]

que determinará de cada opción del select, el texto a mostrar y el valor que tomará la propiedad value al seleccionar dicha opción.

value Any

Propiedad que almacenará el value del item seleccionado.

linked Boolean false

Determina la actualización del formulario contenedor.

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:

{
  link: String,
  text: String
  openNewTab:Boolean
  classes:String
}

En la propiedad text del objeto se determinará el texto que mostrará el hint, esta propiedad debe estar valorizada para que se muestre el hint.

En la propiedad link del objeto se determinará el link al cual navegará al clickear en el hint, si no se encuentra valorizada el hint no será clickeable, solo será texto.

En la propiedad openNewTab del objeto se determinará si al clickearse el hint con link valorizado, se navegará en una nueva pestaña. Solo es útil paracuando la propedad link del objeto está definida. Si no se encuentra definido, se navegará en la misma pestaña.

En la propiedad classes del objeto, se determinarán las clases que se aplicarán al hint, las clases serán separadas por un espacio, sirven para definir estilos. Se utilizarán principalmente clases de vuetify.

Las clases aplicables para las filas de la tabla podrán encontrarse en Vuetify en los siguientes enlaces:

# Código fuente

<template>
  <ir-radio-group-bone
    v-bind="attrs"
    @update-value="updateRadioValue"
    @update-loading="(status) => (isLoadingItems = status)"
    v-on="listeners"
  >
    <template
      #default="{
        rules,
        readonly,
        hideDetails,
        linked,
        label,
        comportamientos,
        comportamientosPositions,
        id_resolver,
        makeQuery,
        originalItems
      }"
    >
      <v-radio-group
        :ref="irRadioGroupRef"
        :value="value"
        v-bind="getFilteredProps"
        :readonly="readonly"
        :hide-details="hideDetails"
        :label="label"
        :loading="isLoading"
        :rules="rules"
        v-on="listeners"
        @change="
          (e) =>
            updateValue({
              newValue: e,
              linked,
              makeQuery,
              comportamientos,
              originalItems
            })
        "
      >
        <v-radio
          v-for="(item, k) in originalItems"
          :key="item.text + k"
          :label="item.text"
          :value="item.value"
          v-bind="itemAttrs"
        >
          <template #label>
            <span
              :class="{
                selected: value === item.value
              }"
            >
              {{ item.text }}
            </span>
          </template>
        </v-radio>
        <template
          v-for="(position, k) in comportamientosPositions"
          #[position]
        >
          <div
            :key="'slot-comportamientos-rg-' + k"
            class="d-flex align-center ir-radio-group__comportamiento"
          >
            <template v-for="(comportamiento, i) in comportamientos">
              <ir-comportamiento
                v-if="
                  (typeof comportamiento.visible === 'undefined' ||
                    comportamiento.visible) &&
                  comportamiento.position === position
                "
                :key="'comportamiento-redio-group-' + i"
                :value="value"
                v-bind="comportamiento"
                :father-component-name="radioGroupComponentName"
                :current_id_resolver="id_resolver"
                @change-field-value="(e) => updateValue(e, linked)"
              />
            </template>
          </div>
        </template>
        <template #message="{ message }">
          <div v-html="message" />
        </template>
      </v-radio-group>
    </template>
  </ir-radio-group-bone>
</template>

<script>
import { ref, computed, onMounted, nextTick } from 'vue'
import IrRadioGroupBone from './IrRadioGroupBone.vue'
import { radioGroupComponentName, apiLinked } from '../../../constants'
import focusAndScrollMixin from '../../../mixins/focusAndScroll'
import { setHintTag } from '../../../helpers/hint'
import { filterProps } from '../../../helpers/filterProps'

export default {
  name: radioGroupComponentName,
  components: {
    IrRadioGroupBone
  },
  inheritAttrs: false,
  props: {
    value: {
      type: undefined,
      required: true
    },
    isFocused: {
      type: Boolean,
      default: false
    },
    loading: {
      type: Boolean,
      default: false
    },
    itemAttrs: {
      type: Object,
      default: () => ({})
    },
    hint: {
      type: [String, Object],
      default: ''
    }
  },
  setup(props, { emit, attrs, listeners, expose }) {
    const irRadioGroupRef = ref(null)
    const otherProps = ref({})
    const isLoadingItems = ref(false)

    const getFilteredProps = computed(() => {
      return filterProps(irRadioGroupRef.value, handledAttrs.value, ['data-cy'])
    })

    const isLoading = computed(() => {
      return props.loading || isLoadingItems.value
    })

    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.value
      delete aux.label
      delete aux.required
      return aux
    })

    onMounted(() => {
      if (props.isFocused) {
        let element = irRadioGroupRef.value.$el.querySelector('input')
        focusAndScrollMixin.methods.focusAndScroll(element) //to do: pasar a helper
      }
      otherProps.value = { ...attrs }
    })

    /**
     * Actualiza el valor de value local y emite evento input, se ejecuta cuando se modifica el value desde bone
     * @param {any} value
     * @returns {void}
     */
    const updateRadioValue = (value) => {
      emit('input', value)
    }

    /**
     * Ejecuta comportamientos apiLinked, actualiza el valor del valueLocal y emite evento changeLinkedValue
     * @param {{newValue: any, linked: Boolean, makeQuery: Function, comportamientos: Array, items: Array}} Options
     * @returns {void}
     */
    const updateValue = ({
      newValue,
      linked,
      makeQuery,
      comportamientos,
      items
    }) => {
      if (comportamientos) {
        const apiLinkedComp = comportamientos.find(
          (comp) => comp.type === apiLinked
        )
        if (typeof apiLinkedComp !== 'undefined') {
          linked = false
          makeQuery(apiLinkedComp, newValue)
        }
      }
      emit('input', newValue)
      nextTick(() => {
        if (linked)
          emit('change-linked-value', {
            action: linked,
            campo: {
              type: radioGroupComponentName,
              props: { ...attrs.props, items }
            }
          })
      })
    }
    expose({
      handledAttrs
    })
    return {
      irRadioGroupRef,
      isLoadingItems,
      getFilteredProps,
      isLoading,
      updateRadioValue,
      updateValue,
      listeners,
      attrs
    }
  }
}
</script>

<style lang="scss" scoped>
.ir-radio-group {
  &__comportamiento {
    gap: 10px;
  }
}
</style>
Last Updated: 4/5/2024, 4:52:19 PM