Better know a framework #19: what is `model.bind` in Aurelia

Reading through some section of Aurelia docs, you will see some code like this (not exactly the same)

<!-- -->
<input type="checkbox" model.bind="item" checked.bind="selectedItem" />

<!-- or -->
<!-- -->
<input type="radio" model.bind="item" checked.bind="selectedItem" />

<!-- or -->
<!-- -->
<select value.bind="selectedItem">
  <option repeat.for="item of activeItems"

You may wonder what model.bind is and why it is needed. Simple answer is: model.bind is a way to associate a value that is not a string to <input/> or <option/> element, as <input/> and <option/> element always convert to string whatever value you assign to their value property. You can test its behavior via copy pasting the following block into your browser console:

let i = document.createElement('input');
i.value = {};
console.log(i.value) // [object Object]

let o = document.createElement('option');
o.value = {};
console.log(o.value) // [object Object]

In two way binding scenarios, Aurelia binding system, upon input event from those <input/> or <select/> elements, will get the value of those elements via element.value and update your view model. And as explained above, property value of <input/> and <option/> are quite problematic when it comes to anything that is not a string. This is where model property is needed. Aurelia will check if model exists and get value from it before it fallback to value property. By having a model.bind binding on those element, a model property will be created, and it can store any value ie. object, array, number…, so you can bind it to anything without worrying about coercion.


Is there any way of giving a hint to the binding of the type of value expected?

public testItem: {name: string, value: number}
<div contenteditable textcontent.two-way="" >
<div contenteditable textcontent.two-way="testItem.value">
console.log(testItem) // {name:"abc", value: "5"}

What I would like that happens, is that aurelia somehow knows that testItem.value is of type(number), so that

console.log(testItem) // {name:"abc", value:5}

This keeps catching me out in code far removed from the data input, where I’m expecting a number, but find that I’m dealing with a string instead.

You can employ a value converter:

<div contenteditable textcontent.two-way="" >
<div contenteditable textcontent.two-way="testItem.value | number">
import { valueConverter } from 'aurelia-framework';

export class NumberConverter {
  fromView(val) {
    return Number(val);

Duh! Of course!


You need toView to support two-way binding. nvm :slight_smile:

1 Like