javascript - Angular 1.5无法读取未定义的属性切片和过滤器

标签 javascript angularjs twitter-bootstrap

我正在尝试使用以下命令创建多选下拉列表 http://bentorfs.github.io/angular-bootstrap-multiselect/ Bentorfs 的图书馆。但是,当我尝试在下拉列表中显示数据时,控制台中出现错误,指出切片和过滤器未定义。它告诉我查看 updateSelectionLists 函数,我不知道可能出了什么问题,但欢迎任何建议,谢谢!

(function () {
'use strict';

var multiselect = angular.module('btorfs.multiselect', ['btorfs.multiselect.templates']);

multiselect.getRecursiveProperty = function (object, path) {
    return path.split('.').reduce(function (object, x) {
        if (object) {
            return object[x];
        } else {
            return null;
        }
    }, object)
};

multiselect.directive('multiselect', ['$filter', '$document', '$log', function ($filter, $document, $log) {
    return {
        restrict: 'AE',
        scope: {
            options: '=',
            displayProp: '@',
            idProp: '@',
            searchLimit: '=?',
            selectionLimit: '=?',
            showSelectAll: '=?',
            showUnselectAll: '=?',
            showSearch: '=?',
            searchFilter: '=?',
            disabled: '=?ngDisabled',
            labels: '=?',
            showTooltip: '=?'
        },
        require: 'ngModel',
        templateUrl: 'multiselect.html',
        link: function ($scope, $element, $attrs, $ngModelCtrl) {
            $scope.selectionLimit = $scope.selectionLimit || 0;
            $scope.searchLimit = $scope.searchLimit || 25;

            $scope.searchFilter = '';

            $scope.resolvedOptions = [];
            if (typeof $scope.options !== 'function') {
                $scope.resolvedOptions = $scope.options;
            }

            if (typeof $attrs.disabled != 'undefined') {
                $scope.disabled = true;
            }

            $scope.toggleDropdown = function () {
                $scope.open = !$scope.open;
            };

            var closeHandler = function (event) {
                if (!$element[0].contains(event.target)) {
                    $scope.$apply(function () {
                        $scope.open = false;
                    });
                }
            };

            $document.on('click', closeHandler);

            var updateSelectionLists = function () {
                if (!$ngModelCtrl.$viewValue) {
                    if ($scope.selectedOptions) {
                        $scope.selectedOptions = [];
                    }
                    $scope.unselectedOptions = $scope.resolvedOptions.slice(); // Take a copy
                } else {
                    $scope.selectedOptions = $scope.resolvedOptions.filter(function (el) {
                        var id = $scope.getId(el);
                        for (var i = 0; i < $ngModelCtrl.$viewValue.length; i++) {
                            var selectedId = $scope.getId($ngModelCtrl.$viewValue[i]);
                            if (id === selectedId) {
                                return true;
                            }
                        }
                        return false;
                    });
                    $scope.unselectedOptions = $scope.resolvedOptions.filter(function (el) {
                        return $scope.selectedOptions.indexOf(el) < 0;
                    });
                }
            };

            $ngModelCtrl.$render = function () {
                updateSelectionLists();
            };

            $ngModelCtrl.$viewChangeListeners.push(function () {
                updateSelectionLists();
            });

            $ngModelCtrl.$isEmpty = function (value) {
                if (value) {
                    return (value.length === 0);
                } else {
                    return true;
                }
            };

            var watcher = $scope.$watch('selectedOptions', function () {
                $ngModelCtrl.$setViewValue(angular.copy($scope.selectedOptions));
            }, true);

            $scope.$on('$destroy', function () {
                $document.off('click', closeHandler);
                if (watcher) {
                    watcher(); // Clean watcher
                }
            });

            $scope.getButtonText = function () {
                if ($scope.selectedOptions && $scope.selectedOptions.length === 1) {
                    return $scope.getDisplay($scope.selectedOptions[0]);
                }
                if ($scope.selectedOptions && $scope.selectedOptions.length > 1) {
                    var totalSelected = angular.isDefined($scope.selectedOptions) ? $scope.selectedOptions.length : 0;
                    if (totalSelected === 0) {
                        return $scope.labels && $scope.labels.select ? $scope.labels.select : 'Select';
                    } else {
                        return totalSelected + ' ' + ($scope.labels && $scope.labels.itemsSelected ? $scope.labels.itemsSelected : 'selected');
                    }
                } else {
                    return $scope.labels && $scope.labels.select ? $scope.labels.select : 'Select';
                }
            };

            $scope.selectAll = function () {
                $scope.selectedOptions = $scope.resolvedOptions;
                $scope.unselectedOptions = [];
            };

            $scope.unselectAll = function () {
                $scope.selectedOptions = [];
                $scope.unselectedOptions = $scope.resolvedOptions;
            };

            $scope.toggleItem = function (item) {
                if (typeof $scope.selectedOptions === 'undefined') {
                    $scope.selectedOptions = [];
                }
                var selectedIndex = $scope.selectedOptions.indexOf(item);
                var currentlySelected = (selectedIndex !== -1);
                if (currentlySelected) {
                    $scope.unselectedOptions.push($scope.selectedOptions[selectedIndex]);
                    $scope.selectedOptions.splice(selectedIndex, 1);
                } else if (!currentlySelected && ($scope.selectionLimit === 0 || $scope.selectedOptions.length < $scope.selectionLimit)) {
                    var unselectedIndex = $scope.unselectedOptions.indexOf(item);
                    $scope.unselectedOptions.splice(unselectedIndex, 1);
                    $scope.selectedOptions.push(item);
                }
            };

            $scope.getId = function (item) {
                if (angular.isString(item)) {
                    return item;
                } else if (angular.isObject(item)) {
                    if ($scope.idProp) {
                        return multiselect.getRecursiveProperty(item, $scope.idProp);
                    } else {
                        $log.error('Multiselect: when using objects as model, a idProp value is mandatory.');
                        return '';
                    }
                } else {
                    return item;
                }
            };

            $scope.getDisplay = function (item) {
                if (angular.isString(item)) {
                    return item;
                } else if (angular.isObject(item)) {
                    if ($scope.displayProp) {
                        return multiselect.getRecursiveProperty(item, $scope.displayProp);
                    } else {
                        $log.error('Multiselect: when using objects as model, a displayProp value is mandatory.');
                        return '';
                    }
                } else {
                    return item;
                }
            };

            $scope.isSelected = function (item) {
                if (!$scope.selectedOptions) {
                    return false;
                }
                var itemId = $scope.getId(item);
                for (var i = 0; i < $scope.selectedOptions.length; i++) {
                    var selectedElement = $scope.selectedOptions[i];
                    if ($scope.getId(selectedElement) === itemId) {
                        return true;
                    }
                }
                return false;
            };

            $scope.updateOptions = function () {
                if (typeof $scope.options === 'function') {
                    $scope.options().then(function (resolvedOptions) {
                        $scope.resolvedOptions = resolvedOptions;
                        updateSelectionLists();
                    });
                }
            };

            // This search function is optimized to take into account the search limit.
            // Using angular limitTo filter is not efficient for big lists, because it still runs the search for
            // all elements, even if the limit is reached
            $scope.search = function () {
                var counter = 0;
                return function (item) {
                    if (counter > $scope.searchLimit) {
                        return false;
                    }
                    var displayName = $scope.getDisplay(item);
                    if (displayName) {
                        var result = displayName.toLowerCase().indexOf($scope.searchFilter.toLowerCase()) > -1;
                        if (result) {
                            counter++;
                        }
                        return result;
                    }
                }
            };

        }
    };
}]);

}());

angular.module('btorfs.multiselect.templates', ['multiselect.html']);

angular.module("multiselect.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("multiselect.html",
    "<div class=\"btn-group\" style=\"width: 100%\">\n" +
    "    <button type=\"button\" class=\"btn btn-default btn-block dropdown-toggle\" ng-click=\"toggleDropdown()\" ng-disabled=\"disabled\">\n" +
    "        {{getButtonText()}}&nbsp;<span class=\"caret\"></span>\n" +
    "    </button>\n" +
    "    <ul class=\"dropdown-menu dropdown-menu-form\"\n" +
    "        ng-style=\"{display: open ? 'block' : 'none'}\" style=\"width: 100%; overflow-x: auto\">\n" +
    "\n" +
    "        <li ng-show=\"showSelectAll\">\n" +
    "            <a ng-click=\"selectAll()\" href=\"\">\n" +
    "                <span class=\"glyphicon glyphicon-ok\"></span> {{labels.selectAll || 'Select All'}}\n" +
    "            </a>\n" +
    "        </li>\n" +
    "        <li ng-show=\"showUnselectAll\">\n" +
    "            <a ng-click=\"unselectAll()\" href=\"\">\n" +
    "                <span class=\"glyphicon glyphicon-remove\"></span> {{labels.unselectAll || 'Unselect All'}}\n" +
    "            </a>\n" +
    "        </li>\n" +
    "        <li ng-show=\"(showSelectAll || showUnselectAll)\"\n" +
    "            class=\"divider\">\n" +
    "        </li>\n" +
    "\n" +
    "        <li role=\"presentation\" ng-repeat=\"option in selectedOptions\" class=\"active\">\n" +
    "            <a class=\"item-selected\" href=\"\" title=\"{{showTooltip ? getDisplay(option) : ''}}\" ng-click=\"toggleItem(option); $event.stopPropagation()\">\n" +
    "                <span class=\"glyphicon glyphicon-remove\"></span>\n" +
    "                {{getDisplay(option)}}\n" +
    "            </a>\n" +
    "        </li>\n" +
    "        <li ng-show=\"selectedOptions.length > 0\" class=\"divider\"></li>\n" +
    "\n" +
    "        <li ng-show=\"showSearch\">\n" +
    "            <div class=\"dropdown-header\">\n" +
    "                <input type=\"text\" class=\"form-control input-sm\" style=\"width: 100%;\"\n" +
    "                       ng-model=\"searchFilter\" placeholder=\"{{labels.search || 'Search...'}}\" ng-change=\"updateOptions()\"/>\n" +
    "            </div>\n" +
    "        </li>\n" +
    "\n" +
    "        <li ng-show=\"showSearch\" class=\"divider\"></li>\n" +
    "        <li role=\"presentation\" ng-repeat=\"option in unselectedOptions | filter:search() | limitTo: searchLimit\"\n" +
    "            ng-if=\"!isSelected(option)\"\n" +
    "            ng-class=\"{disabled : selectionLimit && selectedOptions.length >= selectionLimit}\">\n" +
    "            <a class=\"item-unselected\" href=\"\" title=\"{{showTooltip ? getDisplay(option) : ''}}\" ng-click=\"toggleItem(option); $event.stopPropagation()\">\n" +
    "                {{getDisplay(option)}}\n" +
    "            </a>\n" +
    "        </li>\n" +
    "\n" +
    "        <li class=\"divider\" ng-show=\"selectionLimit > 1\"></li>\n" +
    "        <li role=\"presentation\" ng-show=\"selectionLimit > 1\">\n" +
    "            <a>{{selectedOptions.length || 0}} / {{selectionLimit}} {{labels.itemsSelected || 'selected'}}</a>\n" +
    "        </li>\n" +
    "\n" +
    "    </ul>\n" +
    "</div>\n" +
    "");


 }]);

我的代码首先会显示 html 页面

<div class="col-md-2">
   <form >
    <div class="form-group">
      <label >Syscode</label>

  <multiselect ng-model="rc.syscodes" options="rc.data.zone"> </multiselect>


            </div>
          </form>
       </div>

然后这是 Controller

ReportsController.$inject = ['ReportService','$window', '$q'];
function ReportsController(ReportService, $window, $q){
  var ctrl = this;
  var market = "market";
  var zone = "zone";
  var network = "network";
  var spot_id = "spot_id";
  var spotUUID = "spotUUID";


  ctrl.data = [
    {market:"EastCoastEast CoastEast CoastEast Coast", zone:"1", network:"MTV", window_start_utc: Date.now(), breakUUID: Date.now(), expected_break_time:"TodayToday", break_number:"1", spotUUID:"29389283983298298", break_position:"NA", spot_duration:"NA", spot_id:"2", dc:"3", df:"4", pdn:"NA", pdn2:"NA", pdn3:"NA"},
    {market:"West Coast", zone:"289898", network:"A&E", window_start_utc: Date.now(), breakUUID: Date.now(), expected_break_time:"Today", break_number:"1", spotUUID:"hello", break_position:"NA", spot_duration:"29389283983298298", spot_id:"3", dc:"NA", df:"NA", pdn:"NA", pdn2:"NA", pdn3:"NA"},
    {market:"South Coast", zone:"39898", network:"SCIFY", window_start_utc: Date.now(), breakUUID: Date.now(), expected_break_time:"Today", break_number:"1", spotUUID:"hello", break_position:"NA", spot_duration:"29389283983298298", spot_id:"5", dc:"NA", df:"NA", pdn:"NA", pdn2:"NA", pdn3:"NA"},
    {market:"North Coast", zone:"989894", network:"HBO", window_start_utc: Date.now(), breakUUID: Date.now(), expected_break_time:"Today", break_number:"1", spotUUID:"hello", break_position:"NA", spot_duration:"29389283983298298", spot_id:"6", dc:"NA", df:"NA", pdn:"NA", pdn2:"NA", pdn3:"NA"},
    {market:"East Coast", zone:"5989898", network:"CINEMAX", window_start_utc: Date.now(), breakUUID: Date.now(), expected_break_time:"Today", break_number:"1", spotUUID:"hello", break_position:"NA", spot_duration:"29389283983298298", spot_id:"4", dc:"NA", df:"NA", pdn:"NA", pdn2:"NA", pdn3:"NA"},
    {market:"East Coast", zone:"6989898", network:"Cartoon", window_start_utc: Date.now(), breakUUID: Date.now(), expected_break_time:"Today", break_number:"1", spotUUID:"hello", break_position:"NA", spot_duration:"29389283983298298", spot_id:"NA", dc:"NA", df:"NA", pdn:"NA", pdn2:"NA", pdn3:"NA"}
  ];

  // ctrl.millisToUTCDate = DateService.millisToUTCDate;
  ctrl.results = [];
  ctrl.pageDone = false;
  ctrl.loading_results = false;
  ctrl.search_enabled = false;
  ctrl.searching = false;

  ctrl.sort_by = {
    col:'market',
    reverse: true
  };

  ctrl.dropdowns = {
    air_dates:[],
    syscodes:[]
  };

  ctrl.selections = {
    air_date:null,
    syscode:null
  };

  ctrl.syscodes = [];



  ctrl.sort = function(sort_col){
    if(ctrl.sort_by.col === sort_col){
      ctrl.sort_by.reverse = !ctrl.sort_by.reverse;
    } else {
      ctrl.sort_by.col = sort_col;
      ctrl.sort_by.reverse = false;
    }
  };

  // ctrl.commaFilter = StringService.commaFilter;

  ctrl.selectSyscode = function(){
    ctrl.search_enabled = true;
    ctrl.dropdowns.syscodes = [];
    ReportService.getSyscodes(ctrl.selections).then(function(response){
      ctrl.dropdowns.syscodes = response.data;
      console.log(response.data);
    });
  };

  ctrl.search = function () {
    var defer = $q.defer();
    if (ctrl.search_enabled) {
      ctrl.searching = true;
      ctrl.error = false;
      ctrl.sort_by = {
        col: 'expected_break_time',
        reverse: true
      };
      ctrl.filters = undefined;

      ReportService.getAssets(ctrl.selections).then(function (response) {
        ctrl.results = response.data;
        ctrl.searched_once = true;
        ctrl.searching = false;
        defer.resolve('searched');

      }, function (error) {
        defer.reject('search-error');
        ctrl.error = true;
        ctrl.searching = false;
        ctrl.error_data = error;
      });
    } else {
      defer.resolve('no-search');
    }

    return defer.promise;
  };


  ctrl.downloadCSV = function(){
    if(ctrl.searched_once && !ctrl.searching && ctrl.results != null && ctrl.results.length != 0){
      $window.open('/api/playouts/download-assets-csv?air_date='+ctrl.selections.air_date+'&syscode='+ctrl.selections.syscode);
    }
  };

 //Calls initial air dates
  var init = function(){
    ReportService.getAirDates().then(function(response){
      ctrl.dropdowns.air_dates = response.data;
      console.log(response.data);
      ctrl.pageDone = true;
    });
  };
  init();
}

angular.module('command-center-app').controller('ReportsController', ReportsController);

以及错误消息

TypeError: Cannot read property 'filter' of undefined
    at updateSelectionLists (angular-multiselect.js?nocache=${buildNumber}:71)
    at NgModelController.$ngModelCtrl.$render (angular-multiselect.js?nocache=${buildNumber}:88)
    at ngModelWatch (angular-1.5.3.js?nocache=${buildNumber}:26738)
    at Scope.$digest (angular-1.5.3.js?nocache=${buildNumber}:16860)
    at Scope.$apply (angular-1.5.3.js?nocache=${buildNumber}:17133)
    at done (angular-1.5.3.js?nocache=${buildNumber}:11454)
    at completeRequest (angular-1.5.3.js?nocache=${buildNumber}:11652)
    at XMLHttpRequest.requestLoaded (angular-1.5.3.js?nocache=${buildNumber}:11593)
(anonymous) @ angular-1.5.3.js?nocache=${buildNumber}:13424
(anonymous) @ angular-1.5.3.js?nocache=${buildNumber}:10137
$digest @ angular-1.5.3.js?nocache=${buildNumber}:16887
$apply @ angular-1.5.3.js?nocache=${buildNumber}:17133
done @ angular-1.5.3.js?nocache=${buildNumber}:11454
completeRequest @ angular-1.5.3.js?nocache=${buildNumber}:11652
requestLoaded @ angular-1.5.3.js?nocache=${buildNumber}:11593
angular-1.5.3.js?nocache=${buildNumber}:13424 

TypeError: Cannot read property 'slice' of undefined
        at updateSelectionLists (angular-multiselect.js?nocache=${buildNumber}:69)
        at angular-multiselect.js?nocache=${buildNumber}:92
        at angular-1.5.3.js?nocache=${buildNumber}:26614
        at forEach (angular-1.5.3.js?nocache=${buildNumber}:321)
        at NgModelController.$$writeModelToScope (angular-1.5.3.js?nocache=${buildNumber}:26612)
        at writeToModelIfNeeded (angular-1.5.3.js?nocache=${buildNumber}:26605)
        at angular-1.5.3.js?nocache=${buildNumber}:26599
        at validationDone (angular-1.5.3.js?nocache=${buildNumber}:26526)
        at processAsyncValidators (angular-1.5.3.js?nocache=${buildNumber}:26509)
        at NgModelController.$$runValidators (angular-1.5.3.js?nocache=${buildNumber}:26453)

最佳答案

我检查了多选页面,您缺少一些属性:

 <multiselect ng-model="selection" options="options" id-prop="id" display-prop="name">
 </multiselect>

id-prop 应该是您想要选择“区域”的任何内容,我认为在您的情况下。还有显示 Prop ,我认为在您的情况下也是“区域”。示例:

<multiselect ng-model="selection" options="data" id-prop="zone" display-prop="zone">
     </multiselect>

如果可以的话,如果这不能满足您的需求,您可以选择:Another multiselect

关于javascript - Angular 1.5无法读取未定义的属性切片和过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43523715/

相关文章:

javascript - JQuery 插件 - 重定向计时器出错

JavaScript - ES6 模块支持使用 babel

javascript - 同时使用 typescript 和 javascript 的 Angular 2

backbone.js - 将 twiiter 工具提示与backbone.js 结合使用

jquery - 未捕获的 TypeError (jQuery) - 设置只读

javascript - JavaScript 中是否有将文本替换为其他文本的函数?

javascript - Firefox 上的事件对象

javascript - 使用 AngularJs NgResource 从本地主机加载 JSON 文件

html - AngularDart ng-在表格中重复?

javascript - 如何在 AngularJs 中从另一个 Controller 访问一个 Controller