【问题标题】:How to catch ng-keypress/ $event when clicked outside of div?在 div 之外单击时如何捕获 ng-keypress/$event?
【发布时间】:2020-07-26 15:55:10
【问题描述】:

我正在用 AngularJS 构建一个数独游戏。我想要实现的是捕捉 ng-keypress 即使我在页面上的 div 之外单击。看看http://sudoku.com/,例如,如果您选择一个单元格,然后单击页面上您想要的任何位置,然后,如果您仍然单击任何数字,它将更改单元格中的该数字。我怎样才能做到这一点?

请看下面的 HTML 代码:

<table class="sudoku-board" ng-init="getSudoku()" id="sudoku"
                                   ng-class="{'paused': visible}">
                                <tbody>
                                    <tr class="sudoku-row" ng-repeat="sudoku in sudokuGrid track by $index"
                                        ng-init="row = $index">
                                        <td class="sudoku-col sudoku-cell" ng-repeat="number in sudoku track by $index"
                                            ng-init="col = $index" ng-class="{'highlight': colSelected === col || isHighlight(row, col) || rowSelected === row,
                                            'highlight-number':getValue === number.substring(0, 1), 'selected':isSelected === ((row*10) + col), 'paused': visible}"
                                            ng-click="selectedCell(row, col)"
                                            ng-keydown="insertNum($event, row, col);" tabindex="1">
                                            <span class="cell-value"
                                                  ng-class="{'empty': number === null || number.charAt(number.length-1) === '!', 'default': number !== null, 'paused': visible}"
                                                  ng-bind="number.substring(0, 1)"></span>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>

在 ng-keydown 上我触发了这个功能:

// handle inserted value
$scope.insertNum = function (e, row, col, number) {
    console.log("Number: " + number);
    $scope.selectedCol = col; // get selected column
    $scope.selectedRow = row; // get selected row
    console.log(e);
    if (e !== undefined) {
        var keyCode = e.keyCode || e.charCode; // assign key & char code
        if ((keyCode < 49 || ((keyCode > 57 && keyCode < 97) || keyCode > 105)) && (keyCode !== 8 && keyCode !== 46))
            return false; // if clicked button/ event is not a number or delete/ backspace button -> return false

        if (e.currentTarget.children[0].classList[2] === 'empty') // check if clicked cell is empty
            if (keyCode === 8 || keyCode === 46) { // if clicked delete/ backspace remove the current value
                e.currentTarget.children[0].innerHTML = null;
                $scope.sudokuGrid[row][col] = null;
                $(e.target).removeClass("incorrect");
                $(e.target).removeClass("correct");
                $scope.handleErrorClass();
                $scope.getValue = false;
            }
            else { // when number is clicked
                e.currentTarget.children[0].innerHTML = e.key; //  insert that number in the cell
                $scope.sudokuGrid[row][col] = e.key + "!";
                $scope.checkCurrentNumber(row, col);
                $scope.getCurrentNumber(row, col);

                // if inserted number is correct add class
                if (e.key === $scope.sudokuGridSolved[row][col]) {
                    console.log("Correct");
                    $(e.target).removeClass("incorrect");
                    $(e.target).addClass("correct");
                }
                // add incorrect class if inserted number is not correct
                else {
                    console.log("Incorrect");
                    $(e.target).removeClass("correct");
                    $(e.target).addClass("incorrect");
                }
                //$scope.sudokuGrid[row][col] = e.key;
            }
    }
    else {
        if (number !== null && $("tr:eq(" + $scope.selectedRow + ") td:eq(" + $scope.selectedCol + ") span").hasClass("empty")) {
            $("tr:eq(" + $scope.selectedRow + ") td:eq(" + $scope.selectedCol + ") span").html(number);
            $scope.sudokuGrid[row][col] = number + "!";
            $scope.checkCurrentNumber(row, col);
            $scope.getCurrentNumber(row, col);

            // if inserted number is correct add class
            if ($scope.getValue === $scope.sudokuGridSolved[row][col]) {
                console.log("Correct");
                $("tr:eq(" + $scope.selectedRow + ") td:eq(" + $scope.selectedCol + ")").removeClass("incorrect");
                $("tr:eq(" + $scope.selectedRow + ") td:eq(" + $scope.selectedCol + ")").addClass("correct");
            }
            // add incorrect class if inserted number is not correct
            else {
                console.log("Incorrect!");
                $("tr:eq(" + $scope.selectedRow + ") td:eq(" + $scope.selectedCol + ")").removeClass("correct");
                $("tr:eq(" + $scope.selectedRow + ") td:eq(" + $scope.selectedCol + ")").addClass("incorrect");
            }
        }
    }
    $scope.checkForIdenticalValues();
}

【问题讨论】:

    标签: javascript angularjs events event-handling


    【解决方案1】:

    所以问题是因为ng-keydown&lt;td&gt; 标签上,所以该函数只会在它是当前焦点元素时被调用,但听起来你想从页面上的任何位置响应按键事件.

    您可以通过在 body 标记上使用 ng-keydown 而不是 &lt;td&gt; 来做到这一点,然后使函数广播一个可以从数独组件监听的事件以运行 insertNum 逻辑。像这样:

    <body ng-keydown="onMyKeydownEvent($event)"> 
    

    然后你在run()内绑定$rootScope上的函数来广播一个事件。

    app.run(function($rootScope) {
      $rootScope.onMyKeydownEvent = function(e) {
        $rootScope.$broadcast("MyKeydownEvent", e);
      };
    });
    

    然后将监听器添加到您的组件中。

    $scope.$on("MyKeydownEvent", function(e) {
      // insertNum logic goes here.
    });
    

    您还需要对逻辑进行一些调整,因为 e.currentTarget$scope.selectedCol = col; $scope.selectedRow = row; 之类的内容将不再按预期工作。相反,&lt;td&gt; 标签上的ng-click="selectedCell(row, col)" 应该负责将所需的单元格数据设置到范围内,以便可以在事件中使用。

    【讨论】:

    • 非常感谢,我现在就试试,让你知道结果
    • 好的,所以我将 $event 发送到 console.log,它工作正常 - 你知道我怎样才能捕捉到被按下的键或值吗?
    • $scope.$on("MyKeydownEvent", function(e) { }你可以使用e.keyCode获取密钥。
    • @user13289818 成功了吗?
    • 只是一个问题 - 我在网站上有一个输入字段,当我在输入字段中写一些东西时,它也写在数独单元格中。知道如何不将输入字段中的事件发送到数独单元格吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    • 2017-01-16
    相关资源
    最近更新 更多