2013-02-09 63 views
2

我使用AngularJS和Reveal.js創建幻燈片。顯示需要表格聲明編寫* wrapper *指令AngularJS

<div class="slides"> 
    <section> 
    </section> 
</div> 

水平幻燈片。雖然垂直的滑梯有兩個部分:

<div class="slides"> 
    <section> 
     <section> 
     </section> 
    </section> 
</div> 

我渲染採用了棱角分明此頁:

<div ng-app='myApp' class="reveal"> 
    <div class="slides" ng-controller='MyController'> 
     <section slide ng-repeat="slide in slides"> 
     </section> 
    </div> 
</div> 

<script src="https://raw.github.com/hakimel/reveal.js/master/js/reveal.js"></script> 
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.js"></script> 
</body> 
</html> 

幻燈片與多發步驟應該是垂直的。所有其他人應該是水平的。控制器返回步驟並設置顯示:

function MyController($scope) { 
    $scope.slides = [ 
     { 'steps': ['a'] }, 
     { 'steps': ['b1', 'b2'] }, 
     { 'steps': ['c1'] } 
    ]; 
    setTimeout(function() { 
      Reveal.initialize({ 
       loop: false, 
       transition: Reveal.getQueryHash().transition || 'none' 
      }); 
    }, .1 * 1000); 
} 

指令需要在步驟中添加新的元素和屬性。這裏是我的醜,尷尬的,必要的,像jQuery的指令:

app.directive('slide', function() { 

var wrapContent = function (content) { 
    return '<h1>' + content + '</h1>'; 
}; 

return { 
    restrict: 'A' 
    ,link: function (scope, element, attrs, controller) { 
    // resorting to imparative jQuery way 
    if (scope.slide.steps.length == 1) { 
     element.html(
     wrapContent(scope.slide.steps[0]) 
     ); 
    } else { 
     var sections = ''; 
     for (i=0,len=scope.slide.steps.length; i < len; ++i) { 
     sections += 
      '<section ' + 
      function() { 
      result = ''; 
      if (i !== len-1) { 
       result = 'data-autoslide="1000" '; 
      } 
      return result; 
      }() + 
      '>' + 
      wrapContent(scope.slide.steps[i]) + 
      '</section>'; 
     } 
     element.html(sections); 
    } 
    } 
} 
}); 

我如何寫這使得它看起來像角碼? jsfiddle

我試過編譯,鏈接,替換,ng-switch都無濟於事。

回答

3

由於您在範圍內的slides屬性中定義了所有部分,因此我可能會將整個幻燈片放映到指令中。

<div ng-app='myApp' class='reveal' ng-controller='MyController'> 
    <div slideshow='slides'></div> 
</div> 

指令本身裏面,我會遍歷每個幻燈片,並創建一個<section>元素。對於每張幻燈片,遍歷步驟並創建一個元素(如果有多個)或者一個<h1>元素(如果只有一個元素),則創建一個<section>元素。它可能是這個樣子:

for (var i = 0; i < slides.length; i++) { 
    var section = angular.element("<section>"); 
    var steps = scope.slides[i].steps; 

    if (steps.length == 1) { 
    var content = angular.element("<h1>").html(steps[0]); 
    section.append(content); 
    } else { 
    for (var j = 0; j < steps.length; j++) { 
     var subSection = angular.element("<section>"); 
     if (j < steps.length - 1) 
     subSection.attr('data-autoslide', '1000'); 
     var content = angular.element("<h1>").html(steps[j]); 
     subSection.append(content); 
     section.append(subSection); 
    } 
    } 
} 

然後,您可以追加section該指令的元素。而且,因爲在指令中,我們知道DOM已經完成了構建,所以我們可以將調用Reveal.initialize從控制器(通常不是執行DOM操作或庫調用的最大想法)移動到指令本身。

與幾個小的改動把它放在一起,你可能最終在此的jsfiddle代碼:http://jsfiddle.net/BinaryMuse/CXqAb/

雖然你很可能在指令更聲明樣式寫這樣的代碼,我覺得這可能會更易讀一些,並且在與第三方庫(如Reveal期望某個DOM結構)集成時,可以更容易地創建可預測且乾淨的DOM結構,這比使用一堆DOM元素(ngShow s和ngSwitch他們分散在其中。

+0

在鏈接結束時初始化3方lib消除了愚蠢的'setTimeout'。謝謝。 OTOH,這仍然比角度更強調。 – zhon 2013-02-09 06:21:40

+1

當然,在Angular中看到的古典聲明式風格是必要的。但是,Reveal.js對於它所期望的DOM是如此具體,並且渲染內容的邏輯足夠複雜,所以我可能會在實際項目中以這種方式編寫它,因爲我相信它更具可讀性。(我實際上還沒有成功創建此指令的聲明版本。) – 2013-02-09 08:50:26