AngularJS - 进入Angular UI Bootstrap - Carousel Custom Next()?

时间:2014-01-24 16:08:28

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

我正在尝试实现Angular UI Bootstrap轮播,但我正在使用它进行测验。因此,我不需要普通的Prev()和Next()按钮。

相反,我需要一个自定义的Next()按钮,确保他们在继续下一个问题/答案的“幻灯片”之前选择了答案。

如何挂钩carousel指令函数来运行我的代码然后使用carousel.next()函数?

谢谢, 斯科特

2 个答案:

答案 0 :(得分:4)

没有正式的可能性来实现这一目标。但如果你愿意,这可以被黑客入侵。但我认为最好抓住引导原始的一个,看看角度引导ui源(carousel)并编写自己的包装器。

黑客攻击:

我们必须解决的第一个问题是,如何访问CarouselController。没有公开此API的API,carousel指令创建了一个独立的范围。要获得对此范围的访问权,在指令被angular实例化之后,需要表示轮播的元素。为了达到这个目的,我们可以使用像这样的指令,它必须放在与ng-controller相同的元素上:

app.directive('carouselControllerProvider', function($timeout){
  return {
     link:function(scope, elem, attr){
       $timeout(function(){ 
         var carousel = elem.find('div')[1];
         var carouselCtrl = angular.element(carousel).isolateScope();

         var origNext = carouselCtrl.next;
         carouselCtrl.next = function(){
           if(elem.scope().interceptNext()){
               origNext(); 
           }
         }; 

       });
     }
  };
});

我们必须在$timeout调用中包装我们的代码,等待angular创建隔离范围(这是我们的第一次黑客攻击 - 如果我们不想要这个,我们必须将我们的指令放在旋转木马下。但这是不可能的,因为内容将被替换)。下一步是在更换后找到旋转木马的元素。通过使用函数isolateScope,我们可以访问隔离的范围 - 例如到CarouselController

下一个黑客是,我们必须用我们的实现替换CarouselController的原始下一个函数。但是为了稍后调用原始函数,我们必须保留此函数以供以后使用。现在我们可以替换next函数。在这种情况下,我们调用自己的控制器的函数interceptNext。我们可以通过代表我们控制器的元素的范围来访问这个函数。如果interceptNext返回true,我们会调用轮播的原始下一个功能。当然,您可以将完整的原始下一个功能暴露给我们的控制器 - 但为了演示目的,这已足够。我们定义我们的interceptNext函数:

$scope.intercept = false;
$scope.interceptNext = function(){
   console.log('intercept next');
   return !$scope.intercept;
}

我们现在可以通过一个绑定到next的复选框来控制轮播的$scope.intercept功能。 PLUNKR证明了这一点。

我知道这不完全是你想要的,但是你如何能够做到这一点。

答案 1 :(得分:1)

那个黑客是整洁的迈克尔,我开始为我的需要做类似的事情。但后来才意识到我最终还是应该为开源社区做出贡献。

我刚刚提交了一个拉取请求来更新库,因此当前幻灯片的索引会暴露给Carousel范围。

https://github.com/angular-ui/bootstrap/pull/2089

此更改允许您在轮播模板中使用每个幻灯片行为。

此更改允许我覆盖基本轮播模板,以便例如在第一张幻灯片上“prev”按钮不显示或“next”按钮不会显示最终幻灯片。

您可以为自己的个人需求添加更复杂的逻辑,但以这种方式将当前索引暴露给$ scope是使框架的这一部分更加灵活的一部分。

修改

我为个人使用做了更多更改,但不想提供更接近您所需要的更改。

我修改了carousel指令,将“finish”属性添加到范围。

.directive('carousel', [function () {
    return {
        restrict: 'EA',
        transclude: true,
        replace: true,
        controller: 'CarouselController',
        require: 'carousel',
        templateUrl: 'template/carousel/carousel.html',
        scope: {
            interval: '=',
            noTransition: '=',
            noPause: '=',
            finish: '='
        }
    };
}])

然后,当我声明轮播时,我可以将方法传递给该指令属性,该属性是包含轮播的控制器范围内的方法。

<carousel interval="-1" finish="onFinish">
    ...
</carousel>

这允许我修改我的模板,使其具有如下所示的按钮:

<button ng-hide="slides().length-1 != currentIndex" ng-click="finish()" class="btn next-btn">finish<span class="glyphicon glyphicon-stats"></span></button>

因此它仅在正确的幻灯片上有条件地显示并且通过ng-click它调用carousel的$ scope.finish(),这是指向我为此应用程序创建的控制器中的方法的指针。

有意义吗?

编辑:仅当您不对ng-repeat使用排序功能时才有效。有一个错误会破坏幻灯片的索引以实现此类功能。