Angular custom directive scope not updating as expected

I have several directives that are used on a page in my TypeScript application, and each one has its own controllers to control its own scope. Everything works pretty smoothly so far this is a really strange error.

I have a directive keypad

used in a directive payment

that is being called by my controller order

. I just want my code examples to be minimal for simplicity.

My directive payment

has a controller that has a constructor that has:

$scope.vm = this;

      

I use this pattern a lot. My directive payment

also has a function keypadOnChange()

that is called from the directive keypad

.

// In the payment directive:
public keypadOnChange(keypadDirective: IKeypadDirectiveController): void {

    console.log("keypad is changed");
    console.log(keypadDirective.selection);

    this.manualTenderInputValue = Number(keypadDirective.selectionToString());

    console.log(this.manualTenderInputValue);

}

      

It's worth noting here that it console

displays whatever I expect at the right time.

My template for the directive payment

contains:

<div ng-show="vm.keypadIsVisible" class="square_keypad">

    <div class="white"
         keypad
         onchange="vm.keypadOnChange"></div>

    </div>

<div class="item manual-tender-input-field item-white item-small-padding"
        ng-click="vm.toggleKeypadVisibility()">

    {{ vm.manualTenderInputValue }}

</div>

      

Again, it's worth noting that all features and behavior work as expected - including the vm.keypadIsVisible

one that changes similarly vm.manualTenderInputValue

.

The problem is that it vm.manualTenderInputValue

doesn't update. It displays the corresponding value on page load, and I can console.log()

value it when it changes, which is correct, but I cannot update {{ }}

.

Any thoughts on what I'm missing here?


Update

My directive keypad

handles the change event so it can tell that someone is listening for the change and they can do as they please with the data. Looks like this (and spoiler alert: here's the problem ...)

My keyboard directive has a controller that has these noteworthy lines:

// a public variable:
public onChange: any = null;

// in the constructor:
$scope.$watch("onchange", (v) => { this.onChange = v; });

// in a function invoked by ng-click:
public selectNumber(digit: string, domId?: string): void {
    // ... some other stuff not relevant ...
    this.triggerOnChange();
}

// the triggerOnChange in the keypad directive controller:
public triggerOnChange(): void {
    if (this.onChange) {
        this.onChange(this);
    }
}

      

Now back to mine payment

, which had a template which had a line:

<div class="white"
     keypad
     onchange="vm.keypadOnChange"></div>

      

And the directive payment

has a function keypadOnChange

included in the original message. I entered console.log(this)

and found myself this

referencing a directive controller instance in this context keypad

. And that's the problem!

But ... how can I fix this? (no pun intended)

How do I make it so that it has the correct context (and therefore can update the scope) when run keypadOnChange

in a controller ?payment

this

Finally, I am using this directive keypad

elsewhere and have not encountered this issue.

+3


source to share


1 answer


What I decided to solve was that I could maintain the context this

for the directive controller payment

.


My controller constructor payment

ended up including:

this.keypadChange = this.onKeypadChange.bind(this);

      

So far onKeypadChange()

remained the same:



public keypadOnChange(keypadDirective: IKeypadDirectiveController): void {

    // is now referring to the instance of the controller, NOT the keypad directive:
    console.log(this);
    this.manualTenderInputValue = Number(keypadDirective.selectionToString());

 }

      

Finally, the template that calls the directive keypad

now looks like this:

<div class="white" keypad onchange="vm.keypadChange"></div>

      


Based on the comments and suggestions, I will most likely change some of my attribute names to avoid confusion, but this solution answers my original question.

0


source







All Articles