包装时无法找到指令'uibSlide'所需的控制器'uibCarousel'

时间:2015-10-16 13:33:00

标签: javascript angularjs angularjs-directive angular-ui angular-ui-bootstrap

我有一个包含该carousel指令的指令。当我更换幻灯片对象时,它会出现一个错误,指出“包装时无法找到指令'uibSlide'所需的”控制器'uibCarousel'。“

我设法在一个plunkr中复制它。我添加了一个简单的指令如下:

angular.module('ui.bootstrap.demo').directive('mydir', ['$compile',function($compile){
  function link(scope, element, attrs) {
    scope.$watch('slides', function (value) {
        var template = '<uib-carousel interval="myInterval" no-wrap="noWrapSlides">' +
        '<uib-slide ng-repeat="slide in slides" active="slide.active">' +
          '<img ng-src="{{slide.image}}" style="margin:auto;">' +
          '<div class="carousel-caption">' +
            '<h4>Slide {{$index}}</h4>' +
            '<p>{{slide.text}}</p>' +
          '</div>' +
        '</uib-slide>' +
      '</uib-carousel>;';
        element.empty();
        element.html(template);
        $compile(element.contents())(scope);
    });
  }
  return {
            link: link,
            restrict: 'E'
        };
}]);

我还添加了此功能来替换幻灯片:

  $scope.createNewSlide = function(){
    $scope.slides = [];
    var newWidth = 600 + $scope.slides.length + 1;
    $scope.slides.push({
      image: '//placekitten.com/' + newWidth + '/300',
      text: ['More','Extra','Lots of','Surplus'][slides.length % 4] + ' ' +
        ['Cats', 'Kittys', 'Felines', 'Cutes'][slides.length % 4]
    });
  };

如果您点击替换幻灯片按钮,则仍会显示轮播,但控制台中会显示错误。 http://plnkr.co/edit/IGyaWwXGUa8n2LykMkmV?p=preview

当我更换幻灯片对象时,我是否正在做一些不应该做的事情?

编辑:我注意到的一件事是删除ng-repeat指令不会导致此问题。另一个观察结果是,angular实际上编译了自上次编译指令以来已删除的所有旧DOM元素。我第一次注意到uibSlide正在寻找所需的控制器时,uibSlide实际上是在DOM上的元素。当我通过单击按钮添加新数组时,正在寻找控制器的第一个uibSlide位于已从DOM中删除的元素上。

2 个答案:

答案 0 :(得分:1)

我想出了如何摆脱阻止角度重新编译当前删除的DOM元素的错误。

我更改了链接器函数以保存子范围。当幻灯片阵列发生变化时我会自行销毁它并在之后创建一个新的。

  function link(scope, element, attrs) {
    var childScope
    scope.$watch('slides', function (value) {
        var template = '<uib-carousel interval="myInterval" no-wrap="noWrapSlides">' +
        '<uib-slide ng-repeat="slide in slides" active="slide.active">' +
          '<img ng-src="{{slide.image}}" style="margin:auto;">' +
          '<div class="carousel-caption">' +
            '<h4>Slide {{$index}}</h4>' +
            '<p>{{slide.text}}</p>' +
          '</div>' +
        '</uib-slide>' +
      '</uib-carousel>;';
        element.empty();
        if(childScope)
          childScope.$destroy();
        childScope = scope.$new();
        element.html(template);
        $compile(element.contents())(childScope);
    });
  }

http://plnkr.co/edit/g7wN2LSgbT4s7mULAzoJ?p=preview

答案 1 :(得分:1)

从@ Animal2回答开始,我能够解决问题并通过$templateCache

导入模板
function bannerDirective($compile, $http, $templateCache, $parse) {

    function link(scope, element, iAttrs) {
      var childScope
      scope.$watch('slides', function () {
        var template = $parse(iAttrs.data)(scope);
        $http.get('app/myBanner.html', {cache: $templateCache})
          .success(function(tplContent){
            element.replaceWith($compile(tplContent)(scope));
        });
          element.empty();
        if(childScope)
          childScope.$destroy();
        childScope = scope.$new();
        element.html(template);
        $compile(element.contents())(childScope);
      });
    }

      var directive = {
          restrict: 'E',
          controller: 'BannerController',
          controllerAs: 'bannerCtrl',
          bindToController: true,
          link: link
      };

      return directive;
  }

希望它会有所帮助。