如何使用AngularJS在可折叠面板中延迟加载内容

时间:2013-09-26 15:46:47

标签: ajax twitter-bootstrap angularjs lazy-loading

我正在构建一个使用Bootstrap Collapse组件来渲染一系列面板的应用程序,所有这些面板最初都处于折叠状态。

由于页面可能包含许多此类面板,并且每个面板可能包含大量内容,因此在用户展开任何面板时,通过执行AJAX调用,按需填充这些面板似乎是合适的。

页面的动态内容(包括面板的标记)是使用AngularJS呈现的,我假设可以将Angular配置为绑定到面板元素上的事件,这会导致其内容在延迟时加载扩大。

不幸的是,在查看了AngularJS文档和可用的教程之后,我看不出如何最好地解决这个问题。任何人都可以对它发光吗?

提前致谢,

2 个答案:

答案 0 :(得分:2)

@Tim Coulter,我按照@Stewie的想法创造了一些东西。

它绝对可以改进,但我想这是一个很好的起点。

我已经创建了一个小指令来绑定手风琴面板的click事件。触发click事件后,我通过panel-template=属性传递了面板模板,并更新了面板中使用的main-template

它引用了包含每个面板内容的2个html文件(panel1.html和panel2.html)。 我建议创建一个服务来通过AJAX获取这些文件 - 就像你想要的那样。 在下面的代码中,我为此创建了一个名为dataService的服务,您应该将其绑定到click事件 - 因此当用户点击它时,文件会按需加载。

请注意,mainTemplate是所有手风琴的通用面板,所以当它改变时,所有的手风琴将具有相同的内容,但我假设你想要显示只有一个面板,对吗?!

无论如何,正如我之前所说,可以改进逻辑来修复这些小问题,但我相信核心功能是从那里开始的。 :)

<!doctype html>
<html ng-app="myApp">
  <head>
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
    <script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>  
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js"></script>
    <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>

    <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">

    <script>

    var myApp = angular.module('myApp', []);


    myApp.controller('AccordionDemoCtrl', ['$scope', 'dataService', function ($scope, dataService) {
        $scope.oneAtATime = true;

        $scope.mainTemplate = '';

        $scope.groups = [
          {
            id: "001",
            title: "Dynamic Group Header - 1",
            content: "Dynamic Group Body - 1",
            template: "panel1.html"
          },
          {
            id: "002",
            title: "Dynamic Group Header - 2",
            content: "Dynamic Group Body - 2",
            template: "panel2.html"

          }
        ];

    }]);

    myApp.factory('dataService', [ '$http', function($http){
      return {
          getData: function() {
            return // you AJAX content data here;
          }
      }
    }]);

    myApp.directive('accordionToggle', [function () {
      return {
        restrict: 'C',
         scope: {
         mainTemplate: '=',
         panelTemplate: '@'
       },
       link: function (scope, element, iAttrs) {

         element.bind('click', function(e){

           scope.mainTemplate = scope.panelTemplate;

           scope.$apply();

         });
       }
     };
   }]);


    </script>

  </head>
  <body ng-controller="AccordionDemoCtrl">

  <div class="accordion" id="accordionParent">
    <div class="accordion-group" ng-repeat="group in groups" >
     <div class="accordion-heading">
        <a class="accordion-toggle" main-template="$parent.mainTemplate" panel-template="{{ group.template }}" data-toggle="collapse" data-parent="#accordionParent" href="#collapse{{ $parent.group.id }}">
         Collapsible Group Item {{ $parent.group.id }}
       </a>
     </div>
     <div id="collapse{{ group.id }}" class="accordion-body collapse">
       <div class="accordion-inner">
         <div class="include-example" ng-include="mainTemplate"></div>
       </div>
     </div>
   </div>
 </div>

   </body>
  </html>

答案 1 :(得分:2)

这已经过时了,但问题可能会偶尔出现。我现在发现这是最合适的解决方案而不会污染您的控制器: (myDirective在创建后立即通过AJAX加载其内容。)

<accordion>
  <accordion-group 
    heading=""
    ng-repeat="foo in bar"
    ng-init="status = {load: false}"
    ng-click="status.load = true">

  <myDirective ng-if="status.load"></myDirective>
  </accordion-group>
</accordion>

ng-repeat创建的每个元素都有自己的$ scope,因此单击ab accordion-group将导致仅加载相应的指令。

编辑: 根据延迟和延迟加载的数据大小,您可以考虑使用ng-mouseover而不是ng-click。这样,在用户打开手风琴之前大约100ms开始加载,这可以减少UI的“迟缓”。显然,偶尔加载从未实际点击过的组内容是不利的。