Angular 自定义指令范围未按预期更新

Posted

技术标签:

【中文标题】Angular 自定义指令范围未按预期更新【英文标题】:Angular custom directive scope not updating as expected 【发布时间】:2015-10-20 10:57:11 【问题描述】:

我的 TypeScript 应用程序的页面上使用了一些指令,每个指令都有自己的控制器来管理自己的范围。在出现这个非常奇怪的错误之前,一切都非常顺利。

我的 payment 指令中使用了一个 keypad 指令,该指令由我的 order 控制器调用。为简单起见,我将尽量减少代码示例。

我的payment 指令有一个控制器,它有一个构造函数:

$scope.vm = this;

我经常使用这种模式。我的payment 指令还有一个函数keypadOnChange(),它是从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);


这里值得注意的是console 会在正确的时间显示我期望的所有内容。

payment 指令的模板包含:

<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>

同样,值得注意的是所有功能和行为都按预期工作——包括vm.keypadIsVisible,其更改方式与vm.manualTenderInputValue类似。

问题是vm.manualTenderInputValue 没有得到更新。它在页面加载时显示适当的值,当它改变时我可以console.log()它的值,它是正确的,但我无法更新

对我在这里缺少什么有什么想法吗?


更新

我的keypad 指令处理一个更改事件,因此它可以告诉任何监听更改的人,他们可以随心所欲地处理数据。看起来像这样(和剧透:这就是问题所在......)

我的键盘指令有一个控制器,其中包含以下值得注意的行:

// 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);
    

现在,回到我的payment,它有一个模板,上面有一行:

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

并且payment 指令控制器具有原始帖子中包含的keypadOnChange 函数。我输入了一个console.log(this),发现在那个上下文中,this指的是keypad指令控制器的实例。这就是问题所在!

但是...我该如何解决这个? (没有双关语)

我该如何做到这一点,以便在 payment 控制器上调用 keypadOnChange 时,它仍然具有正确的 this 上下文(因此可以更新范围)?

最后一点,我在其他地方使用了这个keypad 指令并且没有遇到这个问题。

【问题讨论】:

我不确定。但是尝试调用'$scope.$apply();'更新指令中的 manualTenderInputValue 值后。 什么是onchange?它是什么样的绑定?你是如何触发该功能的?您能否尝试隔离问题并在演示中复制它。 你不应该使用 ng-change 而不是 onchange 吗? 你正在做很多工作,Angular 已经准备好为你处理了。控制器中的$scope.vm = this; 应该是指令中的隔离作用域(否则,当两个指令尝试共享控制器时,您将遇到作用域冲突问题。)不要使用$watching onchange 处理程序,而是使用ng-change 你能用小提琴重现这个吗? jsfiddle.net 此外,MCVE 将使您更容易找到问题的解决方案。 ***.com/help/mcve 【参考方案1】:

解决我的问题的方法是确保我可以为 payment 指令控制器维护 this 上下文。


我的 payment 控制器构造函数最终包括:

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

虽然onKeypadChange() 保持不变:

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());

 

最后,调用keypad 指令的模板现在看起来像:

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

根据 cmets 和建议,我可能会更改一些属性名称以避免混淆,但此解决方案回答了我最初的问题。

【讨论】:

以上是关于Angular 自定义指令范围未按预期更新的主要内容,如果未能解决你的问题,请参考以下文章

UIBezierPath 未按预期更新

在 Angular2 ngModel 值未在自定义指令的 onBlur 事件上更新

Angular 4:未执行 <router-outlet> 中的自定义属性指令

未按预期应用约束

AngularJS:$scope.$watch 没有更新从自定义指令上的 $resource 获取的值

Angular 2 中自定义指令