Jaans
Jaans

Reputation: 4638

How to use Aurelia's bindable decorator on a property with getter and setter

I have no problem using the @bindable decorator for a property on a class. E.g.

export class SomeClass {
    @bindable public SomeProperty: Date = new Date();
}

But I'm stumped when it comes to using it with properties that have a getter/setter implementation. E.g.

export class SomeClass2 {
    // Where should the @bindable go now?
    private _someProperty: Date = new Date();

    public get SomeProperty(): Date {
        return this._someProperty;
    }

    public set SomeProperty(value: Date) {
        // Do some manipulation / validation here
        this._someProperty = value;
    }
}

I'm sure I'm missing something simple here...

Upvotes: 5

Views: 2918

Answers (1)

PW Kad
PW Kad

Reputation: 14995

Bindable works by adding a getter and a setter on your property that it uses for observing changes. It's recommended that you utilize the ${propertyName}Changed(newValue, oldValue) callback method to accomplish what you're trying to do. Here is an ES2016 example:

ViewModel

import {bindable} from 'aurelia-framework';

export class MyCustomElement {
  @bindable name;

  _name;
  errorMessage = '';

  nameChanged(newValue) {
    if(newValue.length >= 5 ) {
      this.errorMessage = 'Name is too long';
    }
    else {
      this._name = newValue;
      this.errorMessage = '';
    }
  }
}

View

<template>
  <p>Name is: ${_name}</p>
  <p>Error is: ${errorMessage}</p>
</template>

Note that since ES2016 doesn't have private variables, I'm able to use the private backing field in my View. I'm not sure if you can do this in TypeScript, but if you can't, do note that changing the value of the name property in your code will also trigger the nameChanged callback to fire. So you would need to check if newValue is equal to this._name and ignore it in that case.

Upvotes: 9

Related Questions