2014-11-05 96 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); 
     } 
    }; 
});