ng显示指令更改相关作用域值后不更新

ng-show not updating after directive changes related scope values

本文关键字:作用域 更新 显示 指令 ng      更新时间:2023-09-26

我对ng-show方法有一个问题,因为我将方法设置如下:

我检查了用户名字符串的长度,然而,即使它报告了正确的长度,ng-show方法也不会为我隐藏/显示额外的文本,直到按键之后。我如何让它更新密钥上用户名帮助者文本的可见性

如果你看JS小提琴http://jsfiddle.net/FkAkg/8/

           accountApp.directive("stripCharacters", ['$filter', '$http', function($filter, $http) {
            return {
                restrict: 'C',
                link: function(scope, element) {
                    element.bind("keyup", function() {
                        if(scope.account.username !== undefined) {
                            element.val($filter('stripCharacters')(scope.account.username));
                            if(scope.account.username.length > 2) {
                                scope.toggleShowUsername(true); 
                                scope.usernameMessage = scope.account.usernameAvailable;
                            } else {
                                scope.toggleShowUsername(false);
                            }
                        }
                    });
                }
            }
        }]);

我已经让它在同一个元素上用jQuery隐藏/显示来替换它,但我希望它只在angular中工作。

干杯

详细阐述pkozlowski的评论。。。

我还认为你试图在一个地方做得太多了。该指令的(单一)责任是什么?根据名称,它是"剥离字符"。。。但是,如果你看看你在里面做什么,你会剥离字符,调用方法,并更新指令所在元素之外元素的显示逻辑

我建议你简化指令,把其他东西转移到$watch:

这是你的JSFiddle 的叉子

以及相关代码:

在您的控制器中,我添加了以下内容。。。

$scope.$watch('account.username', function (value) {
   if (value.length > 2) {
      $scope.toggleShowUsername(true);
      $scope.usernameMessage = $scope.account.usernameAvailable;
   } else {
      $scope.toggleShowUsername(false);
   }
});

然后你的指令:

accountApp.directive("stripCharacters", ['$filter', function ($filter) {
   return {
      restrict: 'C',
      require: 'ngModel',
      link: function (scope, element, attrs, ngModel) {
            ngModel.$parsers.unshift(function (value) {
               var stripped = $filter('stripCharacters')(value);
               element.val(stripped);
               return stripped;
            });
      }
   }
}]);

需要明确的是,Mark Rajcok的答案在这里也会起作用,可能对你来说更可取。。。但它缺少一个部分:$setViewValue。如果是这样的话,你只需要将上面指令的链接功能更改为:

link: function (scope, element, attrs, ngModel) {
    element.bind('keyup', function () {
       var value = element.val();
       var stripped = $filter('stripCharacters')(value);
       element.val(stripped);
       ngModel.$setViewValue(stripped);
       scope.$apply();
    });
}

其中$setViewValue用于实际使用正确的值更新模型。以下是的JSFiddle,该解决方案;

我希望所有这些都有帮助。

键控处理程序在Angular的"外部"运行,因此使用scope.$apply()使Angular注意到您更改了showUsername:

...
if(scope.account.username.length > 2) {
   scope.toggleShowUsername(true); 
   scope.usernameMessage = scope.account.usernameAvailable;
} else {
   scope.toggleShowUsername(false);
}
scope.$apply();

以上回答了您的问题,但我推荐@pkozlowski.opensource的回答/评论。