aurelia / framework

The Aurelia 1 framework entry point, bringing together all the required sub-modules of Aurelia.
MIT License
11.75k stars 623 forks source link

Radio model.bind doesn't work if pre-selected value is set to an object #840

Closed codedbypaul closed 7 years ago

codedbypaul commented 7 years ago

I'm submitting a bug report

Please tell us about your environment:

Current behavior: When binding radio buttons with object arrays in Aurelia, setting the pre-selected value to an object doesn't add checked to the radio button. If you assign it to an object stored in an array it works.

Expected/desired behavior:

The pre-selected value should be checked.

Gist with 3 versions below: https://gist.run/?id=e66dd4695f107dcf3ee4563b89b59d8b

bigopon commented 7 years ago

The reason your pre-selected value is not used is because it's not the same object.

There are two way for you to deal with that:

  1. Use the same object in fooValues https://gist.run/?id=88c8c19bd53140cb07f77190f1a94b4f
export class App {
  fooValues = [
    {id: 1, text: 'Foo'},
    {id: 2, text: 'Bar'},
    {id: 3, text: 'Baz'}
  ];
  // Note the following line create new object, thus making it fail to select
  // fooSelected = {id: 1, text: 'Foo'};
  fooSelected = this.fooValues[0];

  barValues = ['1', '2', '3'];
  barSelected = '2'
}
  1. Use a matcher on <input type="radio" />
<!-- foo.html -->
<template>
  <label repeat.for="item of fooValues">
    <!-- introduce a matcher function on input -->
    <input type="radio" model.bind="item" checked.bind="fooSelected" matcher.bind='matcher'>
    ${item}
  </label>
</template>
// foo.js
import {bindable} from 'aurelia-framework';
export class Foo {
  @bindable fooValues;
  @bindable fooSelected;
  @bindable barValues;
  @bindable barSelected;

  /**
   * The matcher instructs aurelia how to compare the two value to determine if it should be selected.
   */
  matcher(oldItem, newItem) {
    return oldItem && newItem && oldItem.id === newItem.id;
  }
}

@codedbypaul html is case insensitive, so it should be <bar></bar> and <foo></foo>, just to avoid future confusion.