9
votes

UPDATE: It looks like this is a known bug: https://github.com/aurelia/templating/issues/253
I am leaving it here for reference / searchability purposes.

The Code:

input-mask.ts (Full code can be seen here)

@customAttribute('input-mask')
@inject(Element)
export class InputMaskCustomAttribute {

    @bindable({ defaultBindingMode: bindingMode.twoWay,
                changeHandler: 'onUnmaskedValueChanged'  })
    unmaskedValue: any;

    onUnmaskedValueChanged(newValue, oldValue) {
        console.log('unmaskedValue updated from inside the custom attribute');
    }

    @bindable
    mask: string;

    attached() {

          this.eventTarget.on('focusout', (e: any) => {
             this.unmaskedValue = (<any>$(this.element)).cleanVal()
             this.fireEvent(e.target, 'input');
          });
    }

  // Code for constructor, fireEvent and to setup the mask...
}

carrier.html

<input input-mask="mask.bind: carrier.airbillMask; unmasked-value.bind: airbill" 
       value.bind="formattedAirbill"/>

UPDATE: To work around this bug, change to unmasked-value.two-way and the binding will work.

carrier.ts

@bindable({ defaultBindingMode: bindingMode.twoWay})
carrier: EntityInterfaces.ICarrier;

@bindable({ defaultBindingMode: bindingMode.twoWay })
formattedAirbill: string;

@bindable({ defaultBindingMode: bindingMode.twoWay, changeHandler: 'onAirbillChanged' })
airbill: string;

onAirbillChanged() {
    console.log('Airbill was set!');
}

The Problem:

The data seems to flow into the @bindable variable just fine. As the mask changes, the value in the custom attribute is changed.

But it does not seem to flow out if changes are made inside the custom-attribute.

Example Scenario: After I edit the value in the input box, and exit the input, the focusout event fires and the console statement that indicates that the unmasked Value was updated from inside the custom attribute prints:

unmaskedValue updated from inside the custom attribute

But (when the input looses focus) the console statement saying that the airbill on the carrier.ts file was updated does not fire when I exit the input box:

This does not fire:
console.log('Airbill was set!');

This seems to show to me that the binding is not really two-way.

The Question:

How can I make this binding two-way? So that when I update unmaskedValue inside the custom-attribute it will update the bound value in the view model?

Note: As a workaround, I was able change unmasked-value.bind to be a method call (on-unmasked-value-changed.call="onUnmaskedValueChanged($event)) and update the value in that method. So I don't NEED this to work. But I would like to know if it is possible for future use.

2
Looks like this is a known bug: github.com/aurelia/templating/issues/253Vaccano
Changing the binding to .two-way (instead of just .bind) in the HTML works around this issue.Vaccano
Looks like this issue was closed, can you use it the way you wanted to now, without the workaround?Matt McCabe

2 Answers

-1
votes

Try to initialize the variable unmaskedValue with default value. Try null, undefined, '' and so on. I have done this before but I don`t remember in which version (certainly it was beta)