2014-11-05 64 views
-1

我试图通过指令来处理水平照片滚动。 在链接中,我想测量容器以处理两个箭头以单击以创建上一个/下一个功能。 钍ECODE如下:Angularjs:如何访问局部或局部范围方法?

app.directive("photos", function() { 
    return { 
     restrict: "E", 
     replace: true, 
     scope: { 
      "photoid": "@", 
      "scrollable": "@", 
      "size": "@", 
      "height": "@", 
      "list": "=", 
      "prefix":"@", 
      "inline": "@", 
      "extension": "@", 
      "class": "@", 
      "slide": "@" 
     }, 
     template: 
     '<div style="position:relative">\n\ 
      <div id="photos{{photoid}}" class="scroller {{class}}" ng-class="[{{scrollable}}]" ng-style="{display:list.length==1?\'inline-block\':\'block\', width: list.length==1?\'{{size||\'171px\'}}\':\'auto\', height: \'{{height||size||\'171px\'}}\'}">\n\ 
       <div ng-repeat="p in list"\n\ 
        ng-style="{\'background-image\': \'url({{prefix}}{{p.file}}.thumb.{{extension||\'jpg\'}})\', width: \'{{size||\'171px\'}}\', height: \'{{height||size||\'171px\'}}\'}"\n\ 
        ng-click="$parent.$parent.openPopoverImageViewer(\'#photos{{photoid}}\', {{$index}})">\n\ 
        <div>{{p.text||p.description}}</div>\n\ 
       </div>\n\ 
      </div>\n\ 
      <div class="prev" ng-if="list.length>1" nng-hide="slide<=0"    ng-click="scope.prev()"></div>\n\ 
      <div class="next" ng-if="list.length>1" nng-hide="slide>=list.length-1" ng-click="scope.next()"></div>\n\ 
     </div>', 
     link: function (scope, el, attrs) { 
      //scope.list = JSON.parse(attrs.list); 
      //.animate({scrollLeft: x}, 200); 
      scope.slide = scope.slide||0; 

      console.log("scope.photos: entering for id = #photos"+scope.photoid); 

      var scroller = $("#photos"+scope.photoid); 
      var container = scroller.parent(); 

      console.log("scope.photos: scroller = "+scroller); 
      console.log("scope.photos: container = "+container); 

      var w = container.width(); 
      var h = container.height(); if (h>768) h = 768; // do not exceed image maximum retina size 
      console.log("scope.photos: container (w,h)=("+w+", "+h+")"); 
      scope.scroller = scroller; 
      scope.container = {width: w, height: h}; 
      scope.image  = {width: h}; 
      //scope.slides = c.length; 
      //scope.slide = index; 
      console.log("scope.photos: after sizing container is "+JSON.stringify(scope.container)); 

      // make it scrollable or not 
      if (scope.list.length*h > w) { 
       scroller.addClass("hScrollable"); 
       console.log("scope.photos: Scroller for "+scope.list.length+" added hScrollable class"); 
      } 
      else { 
       scroller.removeClass("hScrollable"); 
       console.log("scope.photos: Scroller for "+scope.list.length+" removed hScrollable class"); 
      } 
      //console.log("scope.photos: Scroller for "+c.length+" photos (container w="+w+"px, image width="+h+") start scroll at index "+index+", scrolleft= "+x+" and got: "+$(scroller).scrollLeft()); 


      var sw = container.width(); 
       w = scroller.height();  
      var x = scope.slide*w;      // offset at the left border 
      x -= (sw-w)/2;       // center 
      if (x<0) x = 0;      // make sure it's not underleft 

      scroller.scrollLeft(x); 
      //console.log("scope.photos: Scroller for "+c.length+" photos ("+w+"px width) start scroll at index "+index+", scrolleft= "+x+" and got: "+$(scroller).scrollLeft()); 
     }, 
     prev : function() { 
      console.log("scope.photos: prev()"); 
      scope.scroller.scrollLeft(0); 
     }, 
     next : function() { 
      console.log("scope.photos: next()"); 
      scope.scroller.scrollRight(0); 
     } 
    }; 
}); 

不幸的是,它看起来像我无法访问宽度和我得到空容器的高度,如图控制台,如下所示:

[Log] scope.photos: entering for id = #photosImpacReglage (kws.corn.app.js.html, line 196) 
[Log] scope.photos: scroller = [object Object] (kws.corn.app.js.html, line 201) 
[Log] scope.photos: container = [object Object] (kws.corn.app.js.html, line 202) 
[Log] scope.photos: container (w,h)=(null, null) (kws.corn.app.js.html, line 206) 
[Log] scope.photos: after sizing container is {"width":null,"height":null} (kws.corn.app.js.html, line 212) 
[Log] scope.photos: Scroller for 5 removed hScrollable class (kws.corn.app.js.html, line 221) 

而且,我怎么能触发本地范围prev()和next()方法?当我点击方法中的console.log()时,我没有控制台消息?


[更新1] 感谢@ClintPowell我修改的指令和它的作品,除了更换:真。当我发表评论时,应用程序会中断。我不明白。

的的jsfiddle的权利有:enter link description here

+0

你的'next'和'prev'方法不在本地范围内。你已经在指令中定义了它们。他们将无法访问。在'link'函数内部,你可以设置'scope.next = function(){...}'等等。没有足够的上下文让我们知道为什么'scroller.parent()。width()'是null。请张贴plunkr或jsfiddle。 – 2014-11-05 22:32:21

+0

关于前/后,你把我放在正确的道路上。谢谢。 @ClintPowell – 2014-11-06 09:25:38

+0

@ClintPowell我提供了一个小提琴。它几乎可以工作,除非我设置replace:true,那么它会中断。 – 2014-11-06 11:04:53

回答

1

从我的意见:你nextprev方法在局部范围内则没有。你在指令中定义了它们,因此它们不可访问。在你的链接功能中,你可以设置scope.next = function() {...}等,然后他们将可以在你的指令范围内访问。

当您定义replace属性时,角度中断的原因是角度要求指令具有单个根元素。当您定义replace时,它会删除您附加指令的元素,并将其替换为您的模板,如指令中所定义。如果你看看你的jsfiddle代码,你的模板没有单一的根元素,而是三个兄弟divs

如果你想使用replace: true,只是包裹在你的模板中的所有三个要素与单一div,因为我在这里:http://jsfiddle.net/6mhm0tab/5 或者你可以简单地删除replace属性,并使用附带的元素作为根。

祝你好运,希望这会有所帮助。

0

的建议通过@ClintPowel的修复:我的功能并没有连接到的范围。

关于替换问题:真正使angularjs生成DOM异常,我真的没有得到它。除了删除部分中的englobing div使我的指令工作。

虽然我在理解这个错误的全部内容时非常感兴趣,但您仍然可以参考jsFiddle来解决这个问题。

工作代码如下:

app.directive("photos", function() { 
    return { 
     restrict: "E", 
     replace: true, 
     scope: { 
      "photoid": "@", 
      "scrollable": "@", 
      "size": "@", 
      "height": "@", 
      "list": "=", 
      "prefix":"@", 
      "inline": "@", 
      "extension": "@", 
      "class": "@", 
      "slide": "=" 
     }, 
     template: 
     '<div id="photos{{photoid}}Container"\n\ 
      style="position:relative"\n\ 
      ng-style="{display:list.length==1?\'inline-block\':\'block\', width: list.length==1?\'{{size||\'171px\'}}\':\'auto\', height: \'{{height||size||\'auto\'}}\'}">\n\ 
      <div id="photos{{photoid}}"\n\ 
       class="scroller {{class}}"\n\ 
       ng-class="[{{scrollable}}]">\n\ 
       <div ng-repeat="p in list"\n\ 
        ng-style="{\'background-image\': \'url({{prefix}}{{p.file}}.thumb.{{extension||\'jpg\'}})\', width: \'{{size||\'171px\'}}\', height: \'{{height||size||\'171px\'}}\'}"\n\ 
        ng-click="$parent.$parent.openPopoverImageViewer(\'#photos{{photoid}}\', {{$index}})">\n\ 
        <div>{{p.text||p.description}}</div>\n\ 
       </div>\n\ 
      </div>\n\ 
      <div class="prev" ng-if="list.length>1" ng-show="canPrev()" ng-click="prev()"></div>\n\ 
      <div class="next" ng-if="list.length>1" ng-show="canNext()" ng-click="next()"></div>\n\ 
     </div>' 
     , 
     link: function (scope, el, attrs) { 
      scope.doesScroll = function() { 
       var scroller = $("#photos"+scope.photoid); 
       return scope.list.length*(scope.size||171)>scroller.width(); 
      }; 
      scope.canPrev = function() { 
       var scroller = $("#photos"+scope.photoid); 
       return scroller.scrollLeft(); 
      }; 
      scope.canNext = function() { 
       var scroller = $("#photos"+scope.photoid); 
       return scope.list.length*(scope.size||171)>scroller.scrollLeft()+scroller.width(); 
      }; 

      scope.prev = function() { 
       var scroller = $("#photos"+scope.photoid); 
       var l = scroller.scrollLeft(); 
       l -= (scope.size||171); 
       scroller.animate({scrollLeft:l}, 200, function(){ 
        scope.$apply(scope.canPrev); 
        scope.$apply(scope.canNext); 
       }); 
      }; 

      scope.next = function() { 
       //console.log("scope.photos: next()"); 
       var scroller = $("#photos"+scope.photoid); 
       var l = scroller.scrollLeft(); 
       l += (scope.size||171); 
       scroller.animate({scrollLeft:l}, 200, function(){ 
        scope.$apply(scope.canPrev); 
        scope.$apply(scope.canNext); 
       }); 
      }; 

      scope.slide = (scope.slide||0); 
      var l = scope.slide * (scope.size||171); 
      var scroller = $("#photos"+scope.photoid); 
      scroller.animate({scrollLeft:l}, 200); 
      //console.log("scope.photos: entering for id = #photos"+scope.photoid); 
     } 
    }; 
});