AngularJS ngShow and focus

AngularJS ngShow and focus

本文关键字:focus and ngShow AngularJS      更新时间:2023-09-26

试图根据preview变量是否为真来显示Angular中的textarea。在preview设置为true之后,我也想将焦点设置为textarea

控制器逻辑

.controller('MyCtrl', ['$scope', function ($scope) {
    $scope.preview = false;
    $scope.showPreview = function() {
        $scope.preview = true;
    }
}])
<<p> 指令逻辑/strong>
.directive('previewFocus', function() {
    return function(scope, element, attrs) {
       scope.$watch('preview', 
         function (newValue) { 
            newValue && element[0].focus();
         },true);
      };    
});

然后我有一个div,当点击时,它会触发showPreview()方法:

<div ng-click="showPreview()">Add Post</div>

和带有preview-focus指令的textarea:

<textarea class="previewInput" preview-focus></textarea>

我已经调试了代码,一切都按预期执行,包括scope.$watch函数的回调。然而,textarea并不关注。如果我不使用ngShow指令,焦点工作良好。下面是两个JSFiddle示例来展示这两种情况。

Focus不工作: JSFiddle with ngShow

Focus works fine: JSFiddle without ngShow

有谁知道一个好方法来使用ngShow和焦点的元素被显示在同一时间?

Use $timeout:

.directive('previewFocus', function($timeout) {
    return function(scope, element, attrs) {
       scope.$watch('preview', 
         function (newValue) { 
            console.log('preview changed!')
            $timeout(function() {
                newValue && element[0].focus();
            }, 0, false);
         });
      };    
});

这可以工作,因为$timeout将$timeout内的代码的执行延迟到呈现阶段之后(因此在执行了ng-show的$watch之后,当textarea变得可见时)

旁注:我删除了$watch的第二个参数-对于原始变量的$watch来说,深度监视是不必要的。

演示小提琴

有点hack,但是可以完成工作(JSFiddle):

function (newValue) { 
  window.setTimeout(function() {
    newValue && element[0].focus();
  }, 0);
},true);

当然,在这种情况下,Angular的$timeout会被首选。