2013-02-09 8 views
2

Я создаю слайд-шоу, используя AngularJS и Reveal.js. Для выявления требуется формаНаписание * wrapper * директива declarativly 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> 

Слайды с Mutiple шаги должны быть расположены вертикально. Все остальные должны быть горизонтальными. Контроллер возвращает шаги и настройки Reveal:

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> элемент. Для каждого слайда выполните итерацию по этапу и создайте элемент <section> (если его несколько) или элемент <h1> (если есть только один). Это может выглядеть примерно так:

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 и ngSwitch рассеянные среди них.

+0

Инициализация 3-х сторонней библиотеки в конце ссылки устраняет глупую 'setTimeout'. Спасибо. OTOH, это все еще кажется более императивным, чем угловатым. – zhon

+1

Определенно, необходимо, чтобы классический декларативный стиль вы видели в Angular. Но Reveal.js настолько специфичен для DOM, которого он ожидает, и логика для того, что делать, достаточно сложна, что я, вероятно, напишу ее таким образом в реальном проекте, так как считаю, что это более читаемо.(На самом деле я еще не создал декларативную версию этой директивы.) –