将Angular元素的类与元素焦点绑定

7
在我的angular应用程序中,我有多行myelement(angular指令封装了input标记)。每次我需要聚焦/选择/高亮其中之一,样式中的.selected类就可以实现这一点。
在下面的应用程序中,除了将input标记聚焦到selected类之外,其他都正常工作。也就是说,无论哪个元素具有selected类,相应的input标记都应该聚焦。我该如何实现?
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
  <style>
    .container {
      display: flex;
      flex-direction: column;
      width: 600px;
    }
    .notebook {
      display: flex;
      justify-content: center;
    }
    .cell {
      margin: 5px;
      padding: 5px;
    }
    .selected {
      border-style: solid;
      border-color: green;
      border-width: 1px;
      border-left-width: 5px;
    }
  </style>
</head>

<body ng-app="myApp">

<div ng-controller="ListController as listctrl" class="notebook">

  <div class="container">
    <myelement ng-repeat="i in listctrl.list"
        ng-click="listctrl.selected = $index"
        ng-class="{selected : listctrl.selected === $index}"
        class="cell"></myelement>
  </div>
</div>

<script type="text/javascript">
angular
  .module('myApp',[])
  .controller('ListController', function($scope) {
    var listctrl = this;
    listctrl.list = [];
    listctrl.selected = 0;

    listctrl.addCell = function() {
      var x = listctrl.list.length;
      listctrl.list.push(x);
      listctrl.selected = listctrl.list.length - 1;
    }

    listctrl.addCell();

    $scope.$on('add', function (event, message) {
      $scope.$apply(listctrl.addCell);
    });

    $scope.$on('keyUp', function(event) {
      $scope.$apply(function(){
        listctrl.selected = listctrl.selected - 1;
      });
    });

    $scope.$on('keyDown', function(event) {
      $scope.$apply(function(){
        listctrl.selected = listctrl.selected + 1;
      });
    });
  })
  .directive('myelement', function($rootScope){

    return {
      template: '<input style="width: 95%"></input>',
      restrict: 'E',
      link: function (scope, element, attrs) {

        var inputTag = element[0].children[0];
        inputTag.focus();

        element.on('keydown', function(event) {
          if (event.keyCode === 13 && event.shiftKey) {
            $rootScope.$broadcast('add');
          } else if (event.keyCode === 38) {
            $rootScope.$broadcast('keyUp');
          } else if (event.keyCode === 40) {
            $rootScope.$broadcast('keyDown');
          }
        });
      },
      controller: function ($scope) {

      }
    };
  })
</script>

</body>
</html>

ng-class="{selected : listctrl.selected === $index}" 这里不应该在 selected 和 listctrl.selected 之间加上一个 "?" 吗?因为这是一个三元运算符吧?还是我理解有误。 - Dream_Cap
1
@Dream_Cap 这不是一个三元运算符,只是一个对象字面量。 - Phil
你能不能使用类似 element.hasClass('selected') && inputTag.focus() 的东西?你可能需要将指令的 priority 设置为大于 0 的值,这样它的 post-link 函数会在 ngClass 之后运行。 - Phil
4个回答

4
考虑以下示例。它使用了 AngularJS 的现在推荐的 component 功能(自 v1.5 起)。这个示例非常简单,所以您可以很容易地理解正在发生什么以及如何在项目中应用它。 JavaScript
class MainController {

    constructor() {
        this.focused = true;
    }

}

class MyElementController {

    constructor($element) {
        this.$element = $element;
    }

    $onChanges(changes) {
        if (changes.focused.currentValue === true) {
            this.$element[0].getElementsByTagName('input')[0].focus();
        }
    }

}

const myElementComponent = {
    bindings: {
        focused: '<'
    },
    controller: MyElementController,
    template: `<input type="text">`
};

angular
    .module('app', [])
    .controller('MainController', MainController)
    .component('myElement', myElementComponent);

HTML

<body ng-app="app" ng-controller="MainController as vm">
    <my-element focused="vm.focused"></my-element>
</body>

4

 var elementComponent = {
bindings:{
     selected:'<'
  },
  controller:function($element){
     this.$onChanges = function(changes) {
       if(changes.selected.currentValue){
         $element[0].getElementsByClassName('textName')[0].focus()
       }
    }
  },
  template:'<input type="text" class="textName"  style="margin:4px">'
};

var controller = function(){
   this.list = [1];
   this.selected = 1
   this.add = function(){
     var length = this.list.length ;
      this.list.push(length + 1);
      this.selected = length + 1;
   }
};


angular.module('app', [])
       .component('element', elementComponent)
       .controller('appCtrl', controller);
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
</head>
<body ng-app="app" ng-controller="appCtrl as vm" >
<script src="https://rawgit.com/angular/bower-angular/master/angular.min.js"></script>
  <button ng-click="vm.add()">Add New Cell</button>
  <div ng-repeat="item in vm.list"  >
    <element selected="item == vm.selected"  ng-click="vm.selected = item"></element>
  </div>
  Selected Element : {{vm.selected}}
</body>
</html>

这可能符合您的需求。

1

在每次键盘松开/完成时,检查类别,并使用focus()、blur()改变输入状态。如果按下tab键,则preventDefault()。

angular
  .module('myApp',[])
  .controller('ListController', function($scope) {
    var listctrl = this;
    listctrl.list = ['1','2','3'];
    listctrl.selected = 0;

    listctrl.addCell = function() {
      var x = listctrl.list.length;
      listctrl.list.push(x);
      listctrl.selected = listctrl.list.length - 1;
    }

    listctrl.addCell();

    $scope.$on('add', function (event, message) {
      $scope.$apply(listctrl.addCell);
    });

    $scope.$on('keyUp', function(event) {
      $scope.$apply(function(){
        listctrl.selected = listctrl.selected - 1;
      });
    });

    $scope.$on('keyDown', function(event) {
      $scope.$apply(function(){
        listctrl.selected = listctrl.selected + 1;
      });
    });
  })
  .directive('myelement', function($rootScope){
    return {
      template: '<input style="width: 95%"></input>',
      restrict: 'E',
      scope: {},
      link: function (scope, element, attrs) {
        var inputTag = element[0].children[0];
        var updateFocues = function(element) {
          if(element[0].className.indexOf('selected') !== -1) {
            scope.$apply(function() {
              inputTag.focus()
            });
          } else {
            scope.$apply(function() {
              inputTag.blur()
            });
          }    
        }

        element.on('keydown', function(event) {
          if (event.keyCode === 13 && event.shiftKey) {
            $rootScope.$broadcast('add');
          } else if (event.keyCode === 38) {
            $rootScope.$broadcast('keyUp');
          } else if (event.keyCode === 40) {
            $rootScope.$broadcast('keyDown');
          }else if (event.keyCode === 9) {
            event.preventDefault();
          }
        });
        

        scope.$on('keyUp', function() {
          updateFocues(element)
        })
        scope.$on('keyDown', function() {
          updateFocues(element)
        })
      },
      controller: function ($scope) {

      }
    };
  })
 .container {
      display: flex;
      flex-direction: column;
      width: 600px;
    }
    .notebook {
      display: flex;
      justify-content: center;
    }
    .cell {
      margin: 5px;
      padding: 5px;
    }
    .selected {
      border-style: solid;
      border-color: green;
      border-width: 1px;
      border-left-width: 5px;
    }
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>

</head>

<body ng-app="myApp">

<div ng-controller="ListController as listctrl" class="notebook">

  <div class="container">
    <myelement ng-repeat="i in listctrl.list"
        ng-click="listctrl.selected = $index"
        ng-class="{selected : listctrl.selected === $index}"
        class="cell"></myelement>
  </div>
</div>
</body>
</html>


0
建议您使用 CSS(很可能它会满足您的需求)。添加额外的 JS 代码来支持简单的行为并不是一个好的做法。
:focus 选择器 在 W3C 上有解释 例如:
myelement input:focus {
  border-style: solid;
  border-color: green;
  border-width: 1px;
  border-left-width: 5px;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接