Angularjs 在模板内使用光滑的caroussel

Angularjs 在模板内使用光滑的caroussel,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我们的客户要求我们实施kenWheeler slick caroussel: 因为我们的项目是用AngularJs构建的,所以我们发现下面的指令可以作为插件的包装器 该指令在模板内调用,如下所示: <slick dots="true" slides-to-show=3> <div ng-repeat="index in question.getProperty().getDynamicData().getIndexes()"> <span&g

我们的客户要求我们实施kenWheeler slick caroussel:

因为我们的项目是用AngularJs构建的,所以我们发现下面的指令可以作为插件的包装器

该指令在模板内调用,如下所示:

<slick dots="true" slides-to-show=3>
    <div ng-repeat="index in question.getProperty().getDynamicData().getIndexes()">
        <span>
            <img ng-src="{{builtPathToImage(question.getProperty().getDynamicData().getImage($index))}}">
        </span>
        <span>{{question.getProperty().getDynamicData().getLabel($index)}}</span>
    </div>
</slick>

{{question.getProperty().getDynamicData().getLabel($index)}
在代码内部调用模板时,会动态创建
div
。指令运行,div显示在彼此的顶部

编辑:

  • 加载页面后,将创建carroussel中的
    div
根据我的研究,这个问题可能是因为在加载页面时指令是“空的”

Plunkr:点击“搞糟”按钮重新创建问题

编辑结束

关于上下文的更多信息: 该项目使用require.js 角自举

是否有人在模板中使用了这个指示语?如果是这样的话,你能提供一些关于你是如何做到这一点的建议吗


感谢

之所以会出现这种情况,是因为插件本身大幅修改了由
ngRepeat
生成的html,使angular无法更新中继器,因为它不再能够识别结构

为了防止angular在更新中继器时混淆,您可以:

  • 取消初始化插件
  • 更新你的中继器
  • 重新初始化插件
我这里有一个工作示例:

它只通过添加一个
slickApply
方法来稍微修改
angular slick.js
包装器,这样您就可以在控制器中轻松地完成这项工作

更改:

棱角光滑.js

    touchThreshold: '@',
    vertical: '@',
    slickApply: '='  // this is the two way binding that changes the interface
  },
  link: function (scope, element, attrs) {
    var initializeSlick, isInitialized;
    var slider; // slider has been moved from the initializeSlick function to here
    /* 
      This function takes another function as an argument 
       and will reset the slick plugin, call the function, and reload it
    */
    scope.slickApply = function(apply){
        if (isInitialized) {
            slider.unslick();
        }
        apply();
        initializeSlick();
    }
    initializeSlick = function () {
      return $timeout(function () {
        var currentIndex;
        slider = $(element);
index.html

这里唯一改变的是添加了
slick apply
属性,该属性引用
$scope
中的
slick apply
函数

<h1>Hello Plunker!</h1>
<slick init-onload="false" slick-apply='slickApply' data="dataLoaded" slides-to-show="3" dots="true">
  <div ng-repeat="item in items">
    <span>
您也可以在不修改包装器的情况下完成所有这些操作,但这需要您在控制器内执行笨拙的jQuery/angular操作,miron在这里演示了这一点:

我认为您肯定可以改进前一个示例,特别是通过修改包装器,使其能够了解角度集合,但目前它没有这样做。但这显然比我在这里提供的热修复程序要多得多

如果您打算在整个代码中更多地使用这个灵活的库,我绝对建议您使用git repo,以便能够以更易于管理的方式对其进行任何其他更改

但是,由于整个包装器实际上是一个文件,其中甚至没有100行代码,因此我认为直接在代码库中采用它没有任何问题。

不过,如果您想在上游更改中进行合并,我建议将其保留为coffee脚本。但是编译后的输出看起来并不糟糕,所以我想这并不重要。

我不知道您的数据结构是什么样子,但我尽可能地重新创建了您的问题

我简化了数据,仅使用包含任何特定数据(如图像源和标签文本)的对象:

$scope.items = [
  {
    imgSrc: 'http://placekitten.com/325/325',
    label: 'label 1'
  }
];
在循环中,我只使用了ng repeat遍历的当前项的属性:

<div ng-repeat="item in items">
  <span>
    <img ng-src="{{ item.imgSrc }}" alt="{{ item.label}}">
   </span>
   <span>{{ item.label }}</span>
</div>
ng如果删除了slick元素的完整dom结构,那么这正是我们需要的。现在,当您更新数据时,只需将
$scope.dataLoaded
赋值包装在超时函数中,将其放入事件循环。因此,angular有时间移除创建的旧滑溜转盘结构:

$scope.dataLoaded = false;

$timeout(function(){
  $scope.dataLoaded = true;
});

没有答案,但是……这篇文章不错。我们希望以手动方式使用它。用户必须手动滑动卡鲁塞尔。@DavidLaberge您能提供小提琴或弹弓吗?“我几乎可以保证到时候我能解决你的问题。”WillemD'haeseleer补充道requested@DavidLaberge似乎您在新的源代码中缺少了
http
方案。这是一个打字错误,对吗?我希望我编辑了这个问题使它更精确。我认为该指令在加载页面之前填充HTML时有效。这可能是一种可行的方法,但请记住,您需要修改包装器代码,这有时不是最佳解决方案。此包装器代码非常有限,并且没有真正添加任何功能“全部添加”。在这里修改它似乎是最好的做法。如果在生产站点上您依赖于任何前端依赖系统,如bower,那么我建议您提出一个拉取请求:)为了完整性起见,您还应该在unInitializeSlick方法中将变量isInitialized设置为false。此包装非常有限,必须通过拉式请求的繁文缛节在这里似乎已经过时了,我只想获得回购协议的所有权,或者直接将其提交给代码库。它没有许可证,所以没有问题。谢谢你的帮助。尽管如果在caroussel中断的范围内添加一个按钮来更改url,问题仍然存在。我查看了slick carousel的公共api,它没有公开reinit方法来重新绘制carousel,所以我们需要欺骗它来重新创建slick元素。我更新了我的plunk,请看一看:这将重新初始化整个指令,并要求您通过
$timeout
切换一个魔旗,我不喜欢这种方法谢谢@miron我目前正在尝试您的解决方案,willem的,我会在我的环境下让它工作后尽快与您联系。谢谢你的努力
<slick init-onload="false" data="dataLoaded" slides-to-show="3" dots="true"></slick>
<slick ng-if="dataLoaded" init-onload="false" data="dataLoaded" slides-to-show="3" dots="true"></slick>
$scope.dataLoaded = false;

$timeout(function(){
  $scope.dataLoaded = true;
});