Introduction
A group of radio inputs is a type of "single select" interface. Aurelia supports two-way binding any type of property to a group of radio inputs. The examples below illustrate binding number, object, string and boolean properties to sets of radio inputs. In each of the examples there's a common set of steps:
- Group the radios via the
name
property. Radio buttons that have the same value for the name attribute are in the same "radio button group"; only one radio button in a group can be selected at a time. - Define each radio's value using the
model
property. - Two-way bind each radio's
checked
attribute to a "selected item" property on the view-model.
Numbers
Let's start with an example that uses a numeric "selected item" property. In this example each radio input will be assigned a number value via the model property. Selecting a radio will cause it's model value to be assigned to the selectedProductId
property.
export class App {
products = [
{ id: 0, name: 'Motherboard' },
{ id: 1, name: 'CPU' },
{ id: 2, name: 'Memory' },
];
selectedProductId = null;
}
export interface IProduct {
id: number;
name: string;
}
export class App {
products: IProduct[] = [
{ id: 0, name: 'Motherboard' },
{ id: 1, name: 'CPU' },
{ id: 2, name: 'Memory' },
];
selectedProductId: number = null;
}
<template>
<form>
<h4>Products</h4>
<label repeat.for="product of products">
<input type="radio" name="group1"
model.bind="product.id" checked.bind="selectedProductId">
${product.id} - ${product.name}
</label>
<br>
Selected product ID: ${selectedProductId}
</form>
</template>
Objects
The binding system supports binding all types to radios, including objects. Here's an example that binds a group of radios to a selectedProduct
object property.
export class App {
products = [
{ id: 0, name: 'Motherboard' },
{ id: 1, name: 'CPU' },
{ id: 2, name: 'Memory' },
];
selectedProduct = null;
}
export interface IProduct {
id: number;
name: string;
}
export class App {
products: IProduct[] = [
{ id: 0, name: 'Motherboard' },
{ id: 1, name: 'CPU' },
{ id: 2, name: 'Memory' },
];
selectedProduct: IProduct = null;
}
<template>
<form>
<h4>Products</h4>
<label repeat.for="product of products">
<input type="radio" name="group2"
model.bind="product" checked.bind="selectedProduct">
${product.id} - ${product.name}
</label>
Selected product: ${selectedProduct.id} - ${selectedProduct.name}
</form>
</template>
Objects with Matcher
You may run into situations where the object your input element's model is bound to does not have reference equality to any of the object in your checked attribute is bound to. The objects might match by id, but they may not be the same object instance. To support this scenario you can override Aurelia's default "matcher" which is a equality comparison function that looks like this: (a, b) => a === b
. You can substitute a function of your choosing that has the right logic to compare your objects.
export class App {
selectedProduct = { id: 1, name: 'CPU' };
productMatcher = (a, b) => a.id === b.id;
}
export interface IProduct {
id: number;
name: string;
}
export class App {
selectedProduct: IProduct = { id: 1, name: 'CPU' };
productMatcher = (a, b) => a.id === b.id;
}
<template>
<form>
<h4>Products</h4>
<label>
<input type="radio" name="group3"
model.bind="{ id: 0, name: 'Motherboard' }"
matcher.bind="productMatcher"
checked.bind="selectedProduct">
Motherboard
</label>
<label>
<input type="radio" name="group3"
model.bind="{ id: 1, name: 'CPU' }"
matcher.bind="productMatcher"
checked.bind="selectedProduct">
CPU
</label>
<label>
<input type="radio" name="group3"
model.bind="{ id: 2, name: 'Memory' }"
matcher.bind="productMatcher"
checked.bind="selectedProduct">
Memory
</label>
Selected product: ${selectedProduct.id} - ${selectedProduct.name}
</form>
</template>
Booleans
In this example each radio input is assigned one of three literal values: null
, true
and false
. Selecting one of the radios will assign it's value to the likesCake
property.
export class App {
likesCake = null;
}
export class App {
likesCake = null;
}
<template>
<form>
<h4>Do you like cake?</h4>
<label>
<input type="radio" name="group3"
model.bind="null" checked.bind="likesCake">
Don't Know
</label>
<label>
<input type="radio" name="group3"
model.bind="true" checked.bind="likesCake">
Yes
</label>
<label>
<input type="radio" name="group3"
model.bind="false" checked.bind="likesCake">
No
</label>
likesCake = ${likesCake}
</form>
</template>
Strings
Finally, here's an example using strings. This is example is unique because it does not use model.bind
to assign each radio's value. Instead the input's standard value
attribute is used. Normally we cannot use the standard value
attribute in conjunction with checked binding because it coerces anything it's assigned to a string.
export class App {
products = ['Motherboard', 'CPU', 'Memory'];
selectedProduct = null;
}
export class App {
products: string[] = ['Motherboard', 'CPU', 'Memory'];
selectedProduct = null;
}
<template>
<form>
<h4>Products</h4>
<label repeat.for="product of products">
<input type="radio" name="group4"
value.bind="product" checked.bind="selectedProduct">
${product}
</label>
<br>
Selected product: ${selectedProduct}
</form>
</template>