【问题标题】:show or hide popover of a parent element from controller - angularjs从控制器显示或隐藏父元素的弹出窗口 - angularjs
【发布时间】:2017-07-18 06:12:31
【问题描述】:

我有以下 div,里面是一个输入文本。 div 有一个弹出框,我希望在输入文本成为焦点时显示它。如果输入文本失焦,我希望隐藏弹出框。我目前正在尝试使用以下代码来做到这一点:

HTML:

<div id="divParent" bs-popover
    data-trigger="focus click" 
    data-auto-close="1"
    data-placement="bottom"
    class="pswd-popover"
    data-template-url="people/user/user-profile/templates/password-requirements.html">
    <rp-form-input-text
        rp-model="page.userData.password"
        config="page.formConfig.password">
    </rp-form-input-text>
</div>  

型号:

model.password = inputTextConfig({
    id: "password",
    fieldName: "password",
    dataType: "password",
    required: false,
    maxLength: 24,
    modelOptions: {
        allowInvalid: true,
    },
    onFocus: model.getMethod("showPopover")
});

控制器:

vm.showPopover = function () {
    var focus = true;

    $(window).keyup(function (e) {
        var code = (e.keyCode ? e.keyCode : e.which);
        if (code == 9 && focus) {
            $timeout(function() {
                angular.element('#divParent').trigger('click');
            }, 100);
            focus = false;
        }
    });

};

我遇到的问题是我只希望通过选项卡触发 onfocus 功能。因为点击 div 会自动触发 popover 的显示。这就是为什么我有 keyup 功能来检测 div 是否被点击或通过 TAB 访问。另一个问题是我只通过触发 div 的 onclick 来显示和隐藏弹出框。如何在控制器中显示和隐藏父 div 的弹出框?

【问题讨论】:

  • 您使用的是哪个弹出框? UI Bootstrap 的那些?
  • 你可以为它创建一个 js-fiddle

标签: javascript angularjs popover


【解决方案1】:

我已经从字面上实现了这一点 - 仅在选项卡上触发(而不是在单击字段时),但我怀疑您会想要同时包含两者,因此您也可以在下面找到该场景的代码。

您可以使用$popover 服务更精确地控制触发它。

var app = angular.module('app', ['ngAnimate', 'ngSanitize', 'mgcrea.ngStrap']);

app.controller('MainCtrl', function($scope, $popover) {

  // sometimes we don't want to trigger code to show the Popover
  $scope.suspendPopoverAction = false;

  $scope.popover = {
    title: 'HEY',
    content: 'This was triggered by tabbing.'
  };

  var asAServiceOptions = {
    title: $scope.popover.title,
    content: $scope.popover.content,
    trigger: 'manual',
    placement: 'bottom',
    autoClose: true,
    onBeforeShow: function() {
      $scope.activeElement = document.activeElement; // record element with focus
      $scope.suspendPopoverAction = true; // don't trigger blur code
    },
    onShow: function() {
      if ($scope.activeElement) $scope.activeElement.focus(); // restore focus
      $scope.suspendPopoverAction = false; // popup is showing, and focus is back to input, so now safe for blur code
    }
  };

  var myPopover = $popover(angular.element(document.querySelector('#divParent')), asAServiceOptions);

  $scope.inputHasFocus = function() {
    if (!$scope.suspendPopoverAction) {
      myPopover.$promise.then(myPopover.show);
    } else {
      $scope.suspendPopoverAction = false;
    }
  };

  $scope.inputLostFocus = function() {
    if (!$scope.suspendPopoverAction) {
      myPopover.$promise.then(myPopover.hide);
    }
  };

  $scope.inputClicked = function(event) {
    $scope.suspendPopoverAction = true; // prevent popover from showing on click

    // NB: If you want to allow mouse clicks also:
    // 1) use ng-click instead of ng-mousedown in the <input>
    // 2) remove "$scope.suspendPopoverAction = true;" line and replace with:
    //      event.stopPropagation();
    // Doing the above prevents the click triggering the "autoClose: true" option, resulting in flickering of the Popover
  };
});
body {
  padding: 5px !important;
}

.pswd-popover {
  background-color: orange;
  padding: 10px;
  margin: 10px;
}

.myheading {
  margin-bottom: 15px;
}
<!DOCTYPE html>
<html ng-app="app">

<head>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="//cdn.jsdelivr.net/fontawesome/4.5.0/css/font-awesome.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css">
  <link rel="stylesheet" href="//mgcrea.github.io/angular-strap/styles/libs.min.css">
  <link rel="stylesheet" href="//mgcrea.github.io/angular-strap/styles/docs.min.css">
  <script src="//cdn.jsdelivr.net/angularjs/1.5.5/angular.min.js" data-semver="1.5.5"></script>
  <script src="//cdn.jsdelivr.net/angularjs/1.5.5/angular-animate.min.js" data-semver="1.5.5"></script>
  <script src="//cdn.jsdelivr.net/angularjs/1.5.5/angular-sanitize.min.js" data-semver="1.5.5"></script>
  <script src="//mgcrea.github.io/angular-strap/dist/angular-strap.js" data-semver="v2.3.8"></script>
  <script src="//mgcrea.github.io/angular-strap/dist/angular-strap.tpl.js" data-semver="v2.3.8"></script>
  <script src="//mgcrea.github.io/angular-strap/docs/angular-strap.docs.tpl.js" data-semver="v2.3.8"></script>
</head>

<body ng-controller="MainCtrl">

  <h4 class = "myheading">Trigger Popover on Tabbing in Password field only</h4>
  An input for testing Tab:
  <input type="text">

  <div id="divParent" class="pswd-popover">
    Password:
    <input type="text" ng-focus="inputHasFocus()" ng-blur="inputLostFocus()" ng-mousedown="inputClicked($event)">
    <button>Some Button</button>
  </div>

  Another input for testing Tab:
  <input type="text">

</body>

</html>

选择或单击密码字段时显示弹出框:

var app = angular.module('app', ['ngAnimate', 'ngSanitize', 'mgcrea.ngStrap']);

app.controller('MainCtrl', function($scope, $popover) {

  // sometimes we don't want to trigger code to show the Popover
  $scope.suspendPopoverAction = false;

  $scope.popover = {
    title: 'HEY',
    content: 'Triggered by tabbing OR clicking.'
  };

  var asAServiceOptions = {
    title: $scope.popover.title,
    content: $scope.popover.content,
    trigger: 'manual',
    placement: 'bottom',
    autoClose: true,
    onBeforeShow: function() {
      $scope.activeElement = document.activeElement; // record element with focus
      $scope.suspendPopoverAction = true; // don't trigger blur code
    },
    onShow: function() {
      if ($scope.activeElement) $scope.activeElement.focus(); // restore focus
      $scope.suspendPopoverAction = false; // popup is showing, and focus is back to input, so now safe for blur code
    }
  };

  var myPopover = $popover(angular.element(document.querySelector('#divParent')), asAServiceOptions);

  $scope.inputHasFocus = function() {
    if (!$scope.suspendPopoverAction) {
      myPopover.$promise.then(myPopover.show);
    } else {
      $scope.suspendPopoverAction = false;
    }
  };

  $scope.inputLostFocus = function() {
    if (!$scope.suspendPopoverAction) {
      myPopover.$promise.then(myPopover.hide);
    }
  };

  $scope.inputClicked = function(event) {
    // using the below code prevents the click triggering the "autoClose: true" option resulting in flickering
    event.stopPropagation();
  };
});
body {
  padding: 5px !important;
}

.pswd-popover {
  background-color: orange;
  padding: 10px;
  margin: 10px;
}

.myheading {
  margin-bottom: 15px;
}
<!DOCTYPE html>
<html ng-app="app">

<head>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="//cdn.jsdelivr.net/fontawesome/4.5.0/css/font-awesome.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css">
  <link rel="stylesheet" href="//mgcrea.github.io/angular-strap/styles/libs.min.css">
  <link rel="stylesheet" href="//mgcrea.github.io/angular-strap/styles/docs.min.css">
  <script src="//cdn.jsdelivr.net/angularjs/1.5.5/angular.min.js" data-semver="1.5.5"></script>
  <script src="//cdn.jsdelivr.net/angularjs/1.5.5/angular-animate.min.js" data-semver="1.5.5"></script>
  <script src="//cdn.jsdelivr.net/angularjs/1.5.5/angular-sanitize.min.js" data-semver="1.5.5"></script>
  <script src="//mgcrea.github.io/angular-strap/dist/angular-strap.js" data-semver="v2.3.8"></script>
  <script src="//mgcrea.github.io/angular-strap/dist/angular-strap.tpl.js" data-semver="v2.3.8"></script>
  <script src="//mgcrea.github.io/angular-strap/docs/angular-strap.docs.tpl.js" data-semver="v2.3.8"></script>
</head>

<body ng-controller="MainCtrl">

  <h4 class = "myheading">Trigger Popover on Tabbing or Clicking in Password field</h4>
  An input for testing Tab:
  <input type="text">

  <div id="divParent" class="pswd-popover">
    Password:
    <input type="text" ng-focus="inputHasFocus()" ng-blur="inputLostFocus()" ng-click="inputClicked($event)">
    <button>Some Button</button>
  </div>

  Another input for testing Tab:
  <input type="text">

</body>

</html>

还要注意 HTML 中的细微变化。此版本使用&lt;input ng-click="",而仅制表符代码使用&lt;input ng-mousedown=""。此更改可防止与 auto-close: true 关联的闪烁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    • 1970-01-01
    • 2021-05-16
    • 1970-01-01
    相关资源
    最近更新 更多