Saltar al contenido

Ion-radio (Ionic radio button) de 0 a 100

ion-radio Ionic

¿Pensando en incluir radio buttons en tu app de Ionic? o, tal vez, solo quieres conocer más detalles sobre sus campos o funciones ¿verdad?

Si la respuesta es afirmativa a cualquiera de estar preguntas, o cuestiones derivadas de ellas, es algo totalmente normal. Casi todos los desarrolladores, donde me incluyo, tenemos la necesidad de consultar este tipo de artículos de vez en cuando. No podemos tener toda esta información en la cabeza, es imposible.

Y, por si no me conoces aún, mi nombre es Aitor Sánchez y soy desarrollador de software desde el año 2014. Me especializo en apps móviles, y servicios de backend para estas, y en artículo de hoy te explicaré cómo puedes incluir botones de selección en una aplicación hecha con el framework html, Ionic.

Ionic radoi buttons

Pero antes de continuar, este es El Círculo. Es mi newsletter donde te puedo enseñar desarrollo de apps móviles, aso y monetización. Por cierto, si te suscribes te regalo mi ebook Duplica los ingreso de tus apps en 5 minutos. No es broma.

P.D: Darse de alta es gratis y de baja, también.

 

¿Qué es un ion radio button?

Pues para quien no lo sepa, se trata de los típicos botones redondos que se agrupan para seleccionar una opción u otra. Vamos a ver un ejemplo, en forma de demo, antes de continuar:

Ion Radio (Radio button)

¿Y ahora? ¿Mejor? Seguro que sí.

 

Instalación del componente Ionic radio

Este componente no requiere instalación previa. Simplemente podemos usarlo sin problemas llamando a las etiquetas correspondientes. Sigue leyendo.

 

Configuración del módulo

Yeahh! Yujuuuu ¿Qué haces Aitor? Pues nada compañero, simplemente que no requiere configuración tampoco jajajaj. Sigamos.

 

Cómo usar un ion-radio o Radio Button

Que mejor opción para entender algo que ver un ejemplo de uso:

 

<ion-list radio-group [(ngModel)]="relationship">
  <ion-item>
    <ion-label>Friends</ion-label>
    <ion-radio value="friends" checked></ion-radio>
  </ion-item>
  <ion-item>
    <ion-label>Family</ion-label>
    <ion-radio value="family"></ion-radio>
  </ion-item>
  <ion-item>
    <ion-label>Enemies</ion-label>
    <ion-radio value="enemies" [disabled]="isDisabled"></ion-radio>
  </ion-item>
</ion-list>

 

Vale, en primer lugar, tenemos que crear un ion-list llamando a la propiedad radio-group (ion radio group) para que la lista tengas este estilo. ¿Por qué? Ya sabes que Ionic trata todos los inputs como ion-item así que es necesario por esto.

Por otro lado, como puedes ver en el código, bindeamos con el campo relationship. En este campo se guardará el valor de lo que hemos seleccionado.

Continuamos creando un ion-item donde vamos a meter el label y el ion-radio para el que estamos trabajando. Esto es muy simple, lo único que hay que destacar es que el ion-radio tiene una etiqueta “value” que es la que se guardará en nuestra object antes mencionada.

Y listo, esta sería la estructura de uso para este tipo de componente. Tiene algo más de personalización, pero te lo dejo a tu criterio el seguir investigando.

 

Propiedades de entrada de ion-radio

Ahora vamos a ver qué tipo de datos y properties nos ofrece este componente cuando un usuario los usa.

  • checked -> boolean -> Con esta propiedad sabemos que el ion-radio checked está seleccionado o no.
  • color -> string -> Pues como su nombre indica el color del componente.
  • disabled -> boolean -> Con esto activamos y desactivamos el botón para su uso (readonly).
  • value -> any -> Nos permite acceder y setear el valor de nuestro ion-radio. También es accesible desde el formulario en TS con la función getValue().

En el caso de que queramos cambiar el texto (text) asociado, tendremos que cambiar el texto del label, no del value del componente.

 

Eventos de salida de ion-radio

Como he dicho al principio, este es un componente muy simple. Así que solo tiene un evento de salida.

  • ionSelect -> Es emitido cuando el valor (seleccionado/deseleccionado) cambia.

 

ngModel en un Ion Radio o Radio Group ejemplo / example

Otra de las cuestiones principales que me habéis comentado es, que no sabéis cómo podéis bindear un ion radio a través de un ngModel. Pues la respuesta es muy sencilla y la vamos a ver en el siguiente ejemplo:

<ion-list radio-group [(ngModel)]="opcion">
    <ion-list-header>
        Unit
    </ion-list-header>

    <ion-item>
        <ion-label>Opción 1</ion-label>
        <ion-radio value="1"></ion-radio>
    </ion-item>
    <ion-item>
        <ion-label>Opción 2</ion-label>
        <ion-radio value="2" ></ion-radio>
    </ion-item>
    <ion-item> 
        <ion-label>Opción 2</ion-label> 
        <ion-radio value="2" ></ion-radio>
    </ion-item>
</ion-list>

Aunque ya hemos visto algo parecido en el código anterior, la opción más sencilla de hacer el binding es así. El ngModel se usará en el padre «ion-list» con el atributo «radio-group». Digamos que lo usaríamos del mismo modo que usamos un «select». Si pensabas que tenías que añadir el ngModel a los «ion-radio» aquí tienes la solución a tus problemas 🙂

 

‘ion-radio-group’ is not a known element y cómo solucionarlo

En primer lugar, hay que comentar que este error es muy común en la actualidad. Y la base de esto es que en el cambio de versiones de v3 a v4 han cambiado varias cositas. Pero la solución es super sencilla. Basta con que cambiemos nuestro código anterior por algo así:

<ion-list>
  <ion-radio-group [(ngModel)]="opcion">
    <ion-list-header>
      Auto Manufacturers
    </ion-list-header>

    <ion-item>
      <ion-label>Opción 1</ion-label>
      <ion-radio value="1"></ion-radio>
    </ion-item>

    <ion-item>
      <ion-label>Opción 2</ion-label>
      <ion-radio value="2"></ion-radio>
    </ion-item>

    <ion-item>
      <ion-label>Opción 3</ion-label>
      <ion-radio value="3"></ion-radio>
    </ion-item>

    <ion-item>
      <ion-label>Opción 4</ion-label>
      <ion-radio value="4"></ion-radio>
    </ion-item>

    <ion-item>
      <ion-label>Opción 5</ion-label>
      <ion-radio value="5"></ion-radio>
    </ion-item>
  </ion-radio-group>
</ion-list>

En esencia, se ha retirado el componente «radio-group» de la ecuación que se compartía con la etiqueta «ion-list» y ha aparecido como nueva etiqueta «ion-radio-group». Esta última será la encargada de montar todo el sistema de grupo para los radio buttons.

Así que ya sabes, el tema es que el atributo «radio-group» ya no funciona y ahora hay que declararlo así.

 

Los ion-radio no funcionan en un formcontrol / formcontrolname

En esencia mucho me habéis comentado porque no funcionan los ion-radio en los formcontrol cuando lo extraes por el formcontrolname de un form normal y corriente. Después de probarlo me di cuenta de que es cierto, que no terminan de funcionar bien (depende de la versión de Ionic). Es posible que los reactive form de Angular tampoco funcionen por este motivo. Pues una posible solución que he encontrado es la siguiente:

Nota: este ejemplo también nos sirve para todos aquellos quieran bindear un ion-radio con un ngModel.

<ion-row radio-group  formControlName="catchGender" [(ngModel)]="genero" [ngModelOptions]="{standalone: true}">
  <ion-item no-lines>
    <h2>Género</h2>
  </ion-item>
  <ion-col col-4>
    <ion-item no-lines>
      <ion-label>
        <ion-icon name="male"></ion-icon> Hombre</ion-label>
      <ion-radio value="male"></ion-radio>
    </ion-item>
  </ion-col>
  <ion-col col-4>
    <ion-item no-lines>
      <ion-label>
        <ion-icon name="female"></ion-icon> Mujer</ion-label>
      <ion-radio value="female"></ion-radio>
    </ion-item>
  </ion-col>
  <ion-col col-4>
    <ion-item no-lines>
      <ion-label>Unknown</ion-label>
      <ion-radio value="unknown"></ion-radio>
    </ion-item>
  </ion-col>
</ion-row>

Por otro lado, este código también soluciona el problema «no value accessor for form control with name«. He revisado por Github a ver si encontraba algo respecto al tema, y en efecto, esto lo soluciona. Lo chungo de esta excepción reside en el binding de los radios.

Cómo puedes ver, los encerramos en un «radio-group» y los bindeamos a la variable «genero». Así cuando usemos el submit, accedemos a la variable género y ahí estarán los datos. En caso de que el ion-radio este active, devolverá un par con, por ejemplo, {male: true}.

 

Ion-radio con imágenes / with image

Continuamos el artículo hablando de cómo le podemos incluir imágenes a nuestros ion-radio. Directamente no lo podemos hacer, dado que no es permitido, pero aquí os voy a dejar una posible solución al problema. Espero que pueda ser de tu ayuda.

En primer lugar, aquí está el HTML de nuestros «ion-radio». Si te fijas son componentes HTML nativos. También podrías meterlos en un radiogroup si quisieras.

<form>
    <div>
        <input id="a1" type="radio" name="a" value="visa" />
        <label for="a1">Visa</label><br/>
        <input id="a2" type="radio" name="a" value="mastercard" />
        <label for="a2">Mastercard</label>
    </div>
</form>

 

Ahora veamos el style CSS necesario para poner las imágenes:

.cc-selector input{
    margin:0;padding:0;
    -webkit-appearance:none;
       -moz-appearance:none;
            appearance:none;
}

.visa{background-image:url(http://i.imgur.com/lXzJ1eB.png);}
.mastercard{background-image:url(http://i.imgur.com/SJbRQF7.png);}

.cc-selector input:active +.drinkcard-cc{opacity: .9;}

 

Pues listo, ya tenemos nuestros flamantes ion-radio box con las imágenes que queríamos. Es más, y para ir un poquito más allá, usando esto también podríamos cambiar / change el color del background del mismo que hemos puesto la imagen. En lugar de usar «background-image» usaríamos «background-color» o «background» a secas. Sigamos…

 

Cambiemos el color del ionic radio cuando está checked

La siguiente parte que me habéis consultado en varias ocasiones es cómo podemos cambiar el color cuando este está seleccionado. Pues la verdad que es muy sencillo, pero ahí va:

<ion-radio color="secondary" checked></ion-radio>

En caso de que queramos algún color que no esté definido en los base de Ionic. Lo único que tenéis que hacer es ir a vuestra paleta de color base, donde están las variables de compilación de CSS, y crear un color nuevo y ponérselo.

He aprovechado este ejemplo también para mostrar cuando está checked el componente en sí. Así que si estás buscando cómo puedes ponerlo en checked, o un default checked, aquí lo tienes.

 

Cómo saber cuándo cambia de estado

Decir que lo que estamos buscando, un onChange event (ngChange) como tal, no existe en nuestro componente. Pero porque no es necesario que exista, para tal fin vamos a usar el método «ionSelect» (selected event) que se disparará cuando se marque, o desmarque, nuestro componente. Un ejemplo sería el siguiente:

<ion-radio (ionSelect)="radioChecked()" ....>

Basta decir que cuando se marque la casilla se disparará el evento «radioChecked» no confundir con el evento ngChecked en este ejemplo. ¿Lo has entendido? De no ser así, dímelo en los comentarios y le damos un repaso más profundo.

Nota: Este ejemplo también aplicaría para un click event (onClick). Funcionaría exactamente igual.

 

Ahora veamos cómo se crean dinámicamente / dynamic

Este punto es muy interesante, y por el que mucho habéis consultado, y es que tenéis una ligera dificultad en cómo podemos crear radios dinámicamente, por ejemplo, en un *ngFor. Pues bien, primero vamos a ver un ejemplo de código:

<ion-scroll scrollY="true">
<ion-item *ngFor="let user of listOfUsers" [(ngModel)]="selectedUser">
    <ion-label>{{ user.title }}</ion-label>
    <ion-radio [checked]="checkDefault(user)" value="{{ user.value }}" (ionSelect)="OnUserChanged(user)"></ion-radio>
</ion-item>

El objeto sobre el que realizamos la iteración tiene que tener una variable booleana que llamando a la function «checkDefault» nos diga si tenemos que checkearlo cómo pone en el ejemplo para hacer el preselect. Y listo, todo estaría funcionando a las mil y una maravillas 🙂

 

Radio group horizontal, ¿cómo se hace?

Bien, esto es un dilema que he tenido yo también alguna vez, no porque me lo haya preguntado un usuario. Pues bien, la consulta se asemejaría en cómo podemos hacer que los botones se vean de manera horizontal en lugar de vertical. Pues dándole vueltas, la mejor conclusión a la que he llegado es la siguiente:

<ion-radio-group  [(ngModel)]="miVariable">
  <ion-row>
    <ion-col>
        <ion-item>
           <ion-label>A</ion-label>
           <ion-radio mode="md" item-left value="A"></ion-radio>
        </ion-item>
    </ion-col>
    <ion-col>
       <ion-item>
           <ion-label>B</ion-label>
           <ion-radio mode="md" item-left value="B"></ion-radio>
      </ion-item>
    </ion-col>
    <ion-col>
        <ion-item>
            <ion-label>C</ion-label>
            <ion-radio mode="md" item-left value="C"></ion-radio>
       </ion-item>
    </ion-col>
</ion-row>
</ion-radio-group>

Cómo ves, lo único que hemos hecho ha sido llamar a la rejilla de ionic y crear una fila con 3 columnas. En sí mismas, ellas se reparten el espacio, no es necesario asignarles un valor de ancho (o width). Sobre el tema del alto (o height) no será necesario que hagamos nada tampoco. Será el mismo componente el que se encargue de ajustar todo en su sitio.

 

Ahora con estilo de botón

He recordado que una vez, en una app, usé unos radios super chulos, unos ion radio style button. Sobre estaban chulos para Android (para iOS desentonaban un poco, pero bueno) y he encontrado la manera de que lo puedas ver en el artículo. Aquí está:

Nota: Simplemente debéis obviar la parte de «JavaScript» porque son de Angular 1, así que eso no es necesario hacer nada con ello.

1) Incluir el siguiente CSS en nuestra hoja de estilos del componente:

 

ion-content {
  background-color: #fff;
  padding:15px;
}

.radio .radio-icon {
  visibility: visible !important;
}

.radio .radio-icon:before {
  content: "" !important;
  border: 2px solid black !important;
  width: 24px !important;
  height: 24px !important;
  border-radius: 50% !important;
  overflow: hidden !important;
}

.radio .radio-icon:after {
  content: "" !important;
  position: absolute !important;
  right: 20px !important;
  top: 22px !important;
  background: black !important;
  width: 12px !important;
  height: 12px !important;
  border-radius: 50% !important;
  overflow: hidden !important;
  transition: -webkit-transform .28s cubic-bezier(0.420, 0.000, 0.000, 1.650);
  transition: transform .28s cubic-bezier(0.420, 0.000, 0.000, 1.650);
  -webkit-transform: scale(0);
  transform: scale(0);
}

.radio.item-radio > input[type=radio]:checked ~ .radio-icon:after {
  -webkit-transform: scale(1);
  transform: scale(1);
}

.radio .item-content {
  background-color: #fff;
  margin: 0;
  padding-right: 50px;
  padding-left: 0px;
}

.radio.item-radio > input[type=radio]:checked ~ .item-content {
  background-color: #fff;
}

.radio-inline.item {
  display: inline-block;
  border: none;
  margin: 0;
  height: 50px;
}

.radio-blue .radio-icon:after {
  background: #2196F3 !important;
}

.radio-blue .radio-icon:before {
  border-color: #2196F3 !important;
}

.radio-teal .radio-icon:after {
  background: #009688 !important;
}

.radio-teal .radio-icon:before {
  border-color: #009688 !important;
}

.radio-gray .radio-icon:after {
  background: #B6B6B6 !important;
}

.radio-gray .radio-icon:before {
  border-color: #B6B6B6 !important;
}

 

Y ahora utilizaremos la etiqueta de la siguiente manera:

 

<div ng-app="ionicApp">
  <ion-tabs class="tabs-icon-only tabs-positive">

    <ion-tab title="Home" icon="ion-ios7-filing">
      <ion-header-bar class="bar-positive">
        <h1 class="title">Ionic Checkbox</h1>
      </ion-header-bar>

      <ion-content has-tabs="true" ng-controller="HomeCtrl">
        <div>
          <ion-radio class="radio radio-inline radio-gray" ng-model="choice" ng-value="'A'">iOS</ion-radio>
          <ion-radio class="radio radio-inline radio-teal" ng-model="choice" ng-value="'B'">Android</ion-radio>
          <ion-radio class="radio radio-inline radio-blue" ng-model="choice" ng-value="'C'">Windows Phone</ion-radio>
        </div>
      </ion-content>
    </ion-tab>
  </ion-tabs>
</div>

 

¿Verdad que es sencillo? Pues con esto ya lo tendríamos listo.

Nota: en caso de que queramos esconder el icono del componente (o hide ion-radio), o ponerlo transparente (transparent), lo tendríamos que hacer con CSS. Esto no se podría hacer de otra manera por que no hay una variable que nos permita hacerlo. En versiones superiores a Ionic 3 tendríamos que utilizar el siguiente código:

ion-radio{
--color:transparent;
--color-checked: transparent;
}

 

Y en caso contrario, en Ionic 3 y Ionic 2 sería el siguiente:

.radio-md .radio-icon{
    display: none;
}
.item-md{
    border: 1px solid color($colors,divider);
    border-radius: 6px;
}
.item-radio-checked{
    border: 1px solid color($colors,primary);
}

 

Continuamos hablando de estilos y ahora lo que vamos a ver es cómo podemos asignar una posición al check del button. Para ello tenemos que utilizar una etiqueta que todos hemos visto. Se trata, por ejemplo, de «item-left» y la tendremos que setear cómo vemos en el siguiente ejemplo:

En primer lugar, tenemos esto:

<ion-item>
     <ion-label>Etiqueta</ion-label>
     <ion-radio checked="true" value="1"></ion-radio>
</ion-item>

 

Y queremos hacer que el ckeck se vea en el lado izquierdo en lugar del derecho. Para eso vamos a hacer lo siguiente:

<ion-radio checked="true" value="1" item-left></ion-radio>

 

En caso de que queramos ponerlo al otro lado, solo tendríamos que poner item-right en lugar de item-left y listo 🙂

Para los más vaguetes, el videotutorial de la mano de TcRuRav

Más contenidos del curso:

Bueno lector, pues hasta aquí llega el artículo. No tiene más, su uso es así de simple, sencillo y para toda la familia.

Una cosa más, ¿Te gustan los tutos que voy haciendo de esta manera? O ¿Te gustaría que los hiciera de otra manera? Respóndeme por mail y así, a votación popular, intentaré ir adaptando el blog a tu necesidad, que es la mía también.

Un saludo y nos vemos en el siguiente artículo.