删除Angular中动态创建的弹出窗口

Delete a Dynamically Created Popover in Angular

本文关键字:窗口 创建 Angular 动态 删除      更新时间:2023-09-26

我是angular的新手,我已经能够使用以下函数在选定文本周围创建一个引导弹出窗口

 $scope.highlight = function () {
        var a = document.createElement("a");
        a.setAttribute('tabindex', "0");
        a.setAttribute('data-toggle','popover');
        a.setAttribute("id","1");
        a.setAttribute('data-content',"<button type='button' class='btn btn-default' ng-click='deleteLabel()'><small><span class='glyphicon glyphicon-remove'></span></small></button>");
        a.setAttribute('data-html','True');
        if (window.getSelection) {
                var sel = window.getSelection()
                var range = sel.getRangeAt(0).cloneRange();
                range.surroundContents(a);
                sel.removeAllRanges();
                sel.addRange(range);
        }
        $timeout(function(){
          $('[data-toggle="popover"]').popover();
        }, 50);
    };

并且,在上面的代码中,我创建了一个弹出窗口,里面有一个按钮,当点击(ng-click='deleteLabel()')时,应该调用以下函数,该函数应该删除元素

 $scope.deleteLabel= function(){
            alert("removing label");
            var labelEl=document.getElementById("1");
            labelEl.remove();
        };

然而,当点击弹出窗口中的按钮时,deleteLabel()甚至没有被调用。是否有什么问题,我如何从弹出窗口内调用这个函数?

这是一个更Angular的方法,使用ngBootbox;请看工作活塞。一般来说,你希望避免人们在jQuery中做的DOM操作;这就是Angular的优势之一,它可以向你隐藏"复杂性",而使用像ngBootbox这样的指令就是最好的方法。如果你想使用一个jQuery库,那就找一个Angular包装器。

如果我正确理解了你的要求,我有两个弹出窗口…一个用于添加元素,一个用于确认元素的删除。

var app = angular.module('plunker', ['ngBootbox']);
app.controller('MainCtrl', ['$scope', '$ngBootbox', function($scope, $ngBootbox) {
  var vm = this;
  vm.name = 'World';
  vm.categories = ['Category 1', 'Category 2'];
  vm.prompt = function() {
    $ngBootbox.prompt('Enter a new category?')
      .then(function(result) {
        console.log('Prompt returned: ' + result);
        vm.categories.push(result);
      }, function() {
        console.log('Prompt dismissed!');
      });
  }
  vm.delete = function(index) {
    console.log('delete index=' + index + ' v=' + vm.categories[index]);
    $ngBootbox.confirm('Are you sure you want to delete ' + vm.categories[index] + ' ?')
      .then(function(result) {
        // Remove element
        vm.categories.splice(index, 1);
      }, function() {
        // Do nothing
        console.log('Prompt dismissed!');
      });
  }
}]);

要添加,我调用一个提示符,在这里可以输入一个类别,一旦确认,我将它添加到类别数组中,它将自动添加到页面中。

delete使用ng-repeat的$index来知道要删除的元素,如果用户确认删除,我使用splice将其从数组中删除,并且由于Angular的绑定,页面会自动更新。

和HTML:

<body ng-controller="MainCtrl as vm">
  <p>Hello {{vm.name}} !</p>
  <ul>
    <li ng-repeat="c in vm.categories">{{c}} <a href="" ng-click="vm.delete($index)">Delete</a></li>
  </ul>
  <a href="" ng-click="vm.prompt()">Add Category</a> 
</body>

ngBootboxBootbox.js的AngularJS包装器。js允许您轻松地使用Twitter Bootstrap模式的javascript警报,确认和提示。ngBootbox包含三个指令,分别用于alert、confirm和prompt。

Bootbox.js是一个小的JavaScript库,它允许你使用Bootstrap模式创建编程对话框,而不必担心创建、管理或删除任何所需的DOM元素或JS事件处理程序。下面是最简单的例子:

另外,由于你是angular的新手,我使用控制器作为语法和vm=this来避免$scope问题;AngularJS的控制器As和vm变量

这不是正确的做法。你应该通过指令或使用像bootstrap UI

这样的库来操作DOM。

在你的实现中,通过createElement创建的DOM元素没有被绑定。

这是一个使用弹出窗口的工作柱塞。用户选择文本的一部分并单击高亮…然后使用您的代码创建一个链接,并在按下删除按钮时调用删除函数。创建元素后,我调用以下命令使ng-click工作:

  $compile(a)($scope);

我显示内容,并将div标记为'mycontent'作为用于删除所选文本的id:

<body ng-controller="MainCtrl as vm">
  <p id='mycontent'>{{ vm.content }}</p>
  <button ng-click="vm.highlight()">Highlight</button>

  <script type="text/ng-template" id="tpl.html">
    <div class="popover-content">
      <div>
        <div>
          <span>{{link.title}}</span>
        </div>
        <div>
          <button ng-click='vm.delete()'>Delete</button>
        </div>
      </div>
    </div>
  </script>
</body>

我的应用程序是基于你的代码:

var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('MainCtrl', function($scope, $compile, $timeout) {
  var vm = this;
  vm.window = window;
  vm.content = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum';
  vm.delete = function() {
    console.log('delete' + vm.selectedText);
    var d = document.getElementById('mycontent');
    var olddiv = document.getElementById('todelete');
    d.removeChild(olddiv);
  };
  vm.highlight = function() {
    var a = document.createElement("a");
    a.setAttribute('id', 'todelete');
    a.setAttribute('uib-popover', '');
    a.setAttribute('popover-trigger', 'click');
    a.setAttribute('popover-placement', 'top');
    a.setAttribute('ng-click', "info()");
    a.setAttribute('data-html', 'True');
    a.setAttribute('data-content', 'Some content');
    a.setAttribute('uib-popover-template', "'tpl.html'");

    $compile(a)($scope);
    if (window.getSelection) {
      var sel = window.getSelection()
      var text = "";
      if (window.getSelection) {
        text = window.getSelection().toString();
      } else if (document.selection && document.selection.type != "Control") {
        text = document.selection.createRange().text;
      }
      vm.selectedText = text;
      var range = sel.getRangeAt(0).cloneRange();
      range.surroundContents(a);
      sel.removeAllRanges();
      sel.addRange(range);
    }
  };
  vm.getSelectionText = function() {
    var text = "";
    if (window.getSelection) {
      text = window.getSelection().toString();
    } else if (document.selection && document.selection.type != "Control") {
      text = document.selection.createRange().text;
    }
    return text;
  };
});