将焦点设置在添加的项目上

时间:2017-03-21 22:57:19

标签: javascript angularjs angularjs-directive

我想制作一个项目列表,双击一个项目使其可编辑。目前,在编辑项目时,单击外部(即blur)或通过键盘输入会提交新值。

现在,我想添加一个+图标,将项目添加到列表中。 点击+图标后,我希望焦点(和双击)位于添加的项目上,以便我们可以直接修改。

有谁知道如何实现这个目标?

JSBin

<!DOCTYPE html>
<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
  <style>
    input {
      font-size: 20px;
      border:none;
      background-color:transparent;
    }
  </style>
</head>
<body ng-app="app" ng-controller="Ctrl">
  <table>
    <tr ng-repeat="item in items">
      <td>
        <input type="text" value="{{item.name}}" ng-blur='eEditable = -1' ng-readonly='$index !== eEditable' ng-dblclick="eEditable = $index" ng-keypress="keypress($event)"/>
      </td>
    </tr>
  </table>
  <div ng-click="add()">+</div>
  <script>
    var app = angular.module('app', []);
    app.controller('Ctrl', ['$scope', function ($scope) {
      $scope.items = [{ name: "item #1" }, { name: "item #2" }, { name: "item #3" }];
      $scope.eEditable = -1;
      $scope.keypress = function ($event) {
        if ($event.keyCode === 13)
          $event.target.blur()
      }
      $scope.add = function () {
        $scope.items.push({name: "new"});
      }
    }])
  </script>
</body>
</html>

2 个答案:

答案 0 :(得分:1)

当我在角度方面遇到这样的问题时,有时候更容易使用jQuery。

$scope.add = function () {
$scope.items.push({name: "new"});
$scope.eEditable = $scope.items.length-1;
window.setTimeout(function() {
      $("table tr:last td input").focus();
}, 0);

https://jsbin.com/yegokobuna/edit?html,output

我将jQuery代码推送到window.setTimeout(..., 0),以便在角度框架完成呈现HTML元素之后调用代码。

这不是一个很好的解决方案。维护起来比较困难,因为Controller代码现在需要对渲染的HTML有深入的了解。如果我要修改视图以显示一系列div而不是表格行中的项目,那么我将不得不去改变控制器代码。

答案 1 :(得分:0)

这是使用自定义指令的解决方案。 (我保留了JQuery,因为它有两个有用的方法:focusselect

app.directive("customFocus", function() {
  return {
    restrict : "A",
    link: function(scope, element, attrs) {
      scope.$watch(attrs.customFocus, function(newValue) {
        if(newValue) {
          $(element).focus();
          window.setTimeout(function() { $(element).select(); }, 0);
        }
      });
    }
}

现在,您可以将此指令作为属性应用于每个input元素:

<input 
    type="text" 
    value="{{item.name}}" 
    custom-focus='$index == eEditable' 
    ng-blur='eEditable=-1' 
    ng-readonly='$index !== eEditable' 
    ng-dblclick="eEditable = $index" 
    ng-keypress="keypress($event)"/>

控制器中唯一需要的更改是在添加项目时将eEditable设置为等于最终索引:

$scope.add = function () {
   $scope.items.push({name: "new"});
   $scope.eEditable = $scope.items.length-1;
}

https://plnkr.co/edit/3bkJa2FcbTm4uSZ95BNi?p=preview

此解决方案似乎比the pure JQuery solution更优雅,因为使用此解决方案,控制器无需了解呈现的DOM元素。

一个问题是它可以说谎:如果有多个元素带有“custom-focus ='true'”,那么你将会有关于哪个元素实际被授予焦点的未定义行为。< / p>