allencoded allencoded - 6 months ago 104
Javascript Question

Aurelia Two-Way Binding not working properly

I am trying to two-way bind in Aurelia and I can't seem to be able to make it work properly.

So I have create.html which has

selectedTimeZone.two-way="timeZone"
. I am trying to display the fact that it is working and binding by doing
<div if.bind="timeZone">Main: ${timeZone}</div>
. But this never works and the value
timeZone
is never bound.

In
time-zone-picker.html
it does seem to work there. I have
<div if.bind="selectedTimeZone">This is working! ->${selectedTimeZone}</div>
working properly.

Example

Main Template (create.html):

<template>
<require from="../shared/components/time-zone-picker"></require>
<time-zone-picker selectedTimeZone.two-way="timeZone"></time-zone-picker>
<div if.bind="timeZone">Main: ${timeZone}</div>
</template>


time-zone-picker.html:

<template bindable="selectedTimeZone">
<select class="c-select" value.bind="selectedTimeZone">
<option>Select A Time Zone</option>
<option repeat.for="tz of timezones" model.bind="tz">${tz.text}</option>
</select>
<div if.bind="selectedTimeZone">This is working! ->${selectedTimeZone}</div>
</template>


time-zone-picker.js:

import Timezones from 'timezones.json';

export class TimeZonePicker {
constructor() {
this.timezones = Timezones;
}
}


EDIT

Adding the code below to match a response below. Still unable to make it work with the changes below:

time-zone-picker.js

import { bindable, bindingMode } from 'aurelia-framework';
import Timezones from 'timezones.json';

export class TimeZonePicker {
@bindable({ defaultBindingMode: bindingMode.twoWay }) selectedTimeZone;
constructor() {
this.timezones = Timezones;
}
}


time-zone-picker.html

<template>
<select class="c-select" value.bind="selectedTimeZone">
<option>Select A Time Zone</option>
<option repeat.for="tz of timezones" model.bind="tz">${tz.text}</option>
</select>
<div if.bind="selectedTimeZone">${selectedTimeZone}</div>
</template>


create.html

<template>
<require from="../shared/components/time-zone-picker"></require>
<time-zone-picker selectedTimezone.two-way="timeZone"></time-zone-picker>
<div if.bind="timeZone">MAIN ${timeZone}</div>
</template>

Answer

You should use <template bindable="..."> only for html-only custom elements. In your case, you should do this:

time-zone-picker.html

<template> <-- remove bindable here -->
    <select class="c-select" value.bind="selectedTimeZone">
        <option>Select A Time Zone</option>
        <option repeat.for="tz of timezones" model.bind="tz">${tz.text}</option>
     </select>
     <div if.bind="selectedTimeZone">This is working! ->${selectedTimeZone}</div>
</template>

time-zone-picker.js:

import {bindable} from 'aurelia-templating'; // or framework
import {bindingMode} from 'aurelia-binding'; // or framework
import Timezones from 'timezones.json';

export class TimeZonePicker {

  @bindable({ defaultBindingMode: bindingMode.twoWay }) selectedTimeZone;
  constructor() {
    this.timezones = Timezones;
  }
}

create.html

<template>
    <require from="../shared/components/time-zone-picker"></require>
    <time-zone-picker selected-time-zone.two-way="timeZone"></time-zone-picker>
    <div if.bind="timeZone">Main: ${timeZone}</div>
</template>