添加select2腐败模型的Angular Directive?

时间:2014-07-26 02:21:58

标签: jquery angularjs twitter-bootstrap angularjs-directive jquery-select2

我创建了一个带有ng-repeat的表和一个指令,用于在单击其中一个单元格时添加select2 ddl。 一切都运行得很漂亮,所选的值在模型中更新(select2的所有内容都按预期工作),但不知何故,模型似乎因代码中包含此指令而被破坏(我是否从ddl中选择了一个项目) )。

在表格加载数据后,如果我尝试从模型中删除项目(使用拼接):

$scope.Info.splice(index,1);

甚至用原始模型的副本替换整个模型:

$scope.Info = angular.copy($scope.Info2);

我在控制台中收到一条错误,指出'Array.prototype.forEach'为null或不是对象。到目前为止,我只在IE8(我们支持的浏览器)中看到过这种行为。我不认为这会发生在Chrome中。

如果我从指令模板中的输入中删除了“click-to-edit-select2”,我没有看到错误,所以我不禁认为这是指令中的问题,甚至更糟,在select2脚本中,我不知道如何精确定位(希望不是)。

提前道歉!我开始创建一个plunk,但意识到plunks在IE中不起作用,因此很难看到我所指的错误。

我还应该提一下,我们不仅支持IE8,还使用旧版本的脚本:   angular.js:1.2.19   select2-min.js:3.4.8   ui-bootstrap:0.8.0(和模板)   bootstrap.js:2.3.1   bootstrap.css:2.3.1

请查看代码并告诉我是否有办法消除此错误:

HTML:

<body ng-app="app" ng-controller="TestController">
<table class="table table-bordered">
        <thead>
          <tr role="row">
            <th tabindex="0" class="sorting" aria-label="" ng-click="predicate = 'Id'; reverse=!reverse">
              ID
            </th>
            <th tabindex="0" class="no_edit sorting" aria-label="">
              Description
            </th>
          </tr>
        </thead>
        <tbody ng-repeat="item in Info">
          <tr>
            <td click-to-edit-select2="item.id">
              {{item.Id}}
            </td>
            <td>
              {{item.Description}}
            </td>
          </tr>
        </tbody>
      </table>
</body>

控制器:

var app = angular.module("app", ["ui.select2", "ui.bootstrap", "click-to-edit-select2"]);
app.controller('TestController', function($scope, $http, $element, $filter, $modal) {
  $scope.Info2 = [{
    "UniqueIndex": "t1",
    "Status": "",
    "Id": "1",
    "Description": "This Description",

  }, {
    "UniqueIndex": "t2",
    "Status": "",
    "Id": "2",
    "Description": "That Description",

  }];

  //This works . . .initializing the table, before the directive is applied
  $scope.Info = angular.copy($scope.Info2); 


  $scope.DeleteRow = function(item) {
        //Either one of these statements throws the error in the console, 
        //and the model is not updated in the view
        $scope.Info = angular.copy($scope.Info2);
        $scope.Info.splice(0, 1);

    }

})

指令:

angular.module('click-to-edit-select2', [])
  .directive("clickToEditSelect2", function() {
      var editorTemplate = '<td class="click-to-edit-select2">' +
      '<div style="height:20px" ng-click="enableEditor()" ng-hide="view.editorEnabled">' +
      '{{value}} ' +
      '</div>' +
      '<div ng-show="view.editorEnabled" ng-click="save()">' +
      '<input type="hidden" ui-select2="select2Options" ng-model="view.editableValue" ng-change="changeText()" />' +
      '</div>' +
      '</td>';

      return {
          restrict: "A",
          replace: true,
          template: editorTemplate,
          scope: {
              value: "=clickToEditSelect2"
          },
          controller: function($scope, $element, $attrs) { 
              $scope.view = {
                  editorEnabled: false
              };

              $scope.enableEditor = function() {

                      $scope.view.editorEnabled = true;
                      $scope.view.editableValue = $scope.value;

              };

              $scope.disableEditor = function() {
                  $scope.view.editorEnabled = false;
              };

              $scope.save = function() {
                  $scope.value = $scope.view.editableValue.id;
                  $scope.disableEditor();
              };


              var initSelectionCb = function(item, callback) {
                  if (item != "") {
                      var id = item.val();
                      var data = { id: id, text: id };
                      callback(data);
                  }
              };

              $scope.select2Options = { 
                  placeholder: "Select",
                  multiple: false,
                  width: "resolve",
                  initSelection: function(item, callback) {
                      //selects the initial item
                      initSelectionCb.call(self, item, callback);
                  },
                  ajax: {

                      url: "/GetDropDownListForSelect2",
                      type: "POST",
                      contentType: "application/json",
                      data: function(term, page) {

                          var Json = {};
                          Json.term = term;
                          Json.page = page;

                          return Json;

                      },
                      results: function(data, page) {
                          return { results: data.options };
                      }
                  }
              }


          }
      };
  });

2 个答案:

答案 0 :(得分:2)

呼!我能够找到答案here

我将以下代码放在脚本文件的顶部,错误消失了,拼接和复制方法现在在IE8中工作:

if (!('forEach' in Array.prototype)) {
    Array.prototype.forEach = function(action, that /*opt*/) {
        for (var i = 0, n = this.length; i < n; i++)
            if (i in this)
            action.call(that, this[i], i, this);
    };
}

答案 1 :(得分:0)

查看IE8的Angular指南,它并不完全支持。也就是说,有一件事你可以尝试解决这个问题,这会改变你的

<body ng-app="app" ng-controller="TestController">

<body ng-app="app" id="ng-app" ng-controller="TestController">

并将角度命名空间添加到页面顶部。

<html xmlns:ng="http://angularjs.org">

您可以查找here

编辑:为了将来的参考,codenewbie可以解决下面的Array.prototype.Foreach问题。如果您遇到这个问题,请务必阅读。