Search code examples
bindingaureliareadonlycustom-element

How to bind "readonly" in custom element in Aurelia?


I have the following element in html file:

<require from="_controls/time-slot-slider"></require>

    <time-slot-slider id="zeitraum" min="0" max="24" length="4" value="4"
                              value.two-way="functionConfig.startTime" if.bind="functionConfig.isAutomatic === true"
                              readonly.bind="!mayFunctionTestEditTime"></time-slot-slider>

Custom element is here(time-slot-slider.html):

<template class="range-slider time-slot">
  <div>${duration}</div>
  <input type="range" min.bind="min" max.bind="maxStart" step.bind="step" value.bind="value">
</template>

and time-slot-slider.ts :

import { bindable, customElement } from 'aurelia-templating'
import moment from 'moment/moment'
import Moment = moment.Moment

@customElement('time-slot-slider')
export class TimeSlotSlider {

  @bindable public min: number = 0.0
  @bindable public max: number = 24.0
  @bindable public step: number = 0.5
  @bindable public value: number = 0.0
  @bindable public length: number = 4.0

  public get maxStart (): number {
    return this.max - this.length
  }

  public get from (): Moment {
    return TimeSlotSlider.numberToMoment(this.value)
  }
....

But readonly.bind doesn't work. I tried to bind readonly by

@bindable readOnly: boolean but I didn't have any success. How can I fix it?


Solution

  • I believe the problem is that you only apply readonly to your custom element:

    <time-slot-slider readonly.bind="!mayFunctionTestEditTime"></time-slot-slider>
    

    You've mentioned that you'd tried defining @bindable readOnly: boolean on the component's viewmodel, but I assume you had forgotten to apply it to the input itself. Obviously, just the presence of it won't magically cause it to be applied the the input, therefore like that, you basically have a property on your viewmodel that you don't use for anything.

    The solution is to keep that @bindable readonly: boolean property on the VM but also bind its value to the actual input - essentially "forwarding" the value the component gets down to the actual control:

    <input type="range" readonly.bind="readonly" ... />
    

    It is also a good idea to give the properties a default value, see this answer (especially the comments) for details as to why.