【问题标题】:How to use AngularJS to lazy load content in a collapsible panel如何使用 AngularJS 在可折叠面板中延迟加载内容
【发布时间】:2013-09-26 15:46:46
【问题描述】:

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

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

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

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

提前致谢,

提姆

【问题讨论】:

  • 只需在面板中使用<div ng-include="panelTemplate"></div> 并在打开面板时定义/设置panelTemplate var。这将仅在第一次打开面板时执行 XHR 请求并获取面板视图。
  • 谢谢 Stewie。这看起来是一种很有前途的方法,但我不清楚如何在面板打开时触发 panelTemplate 的定义/设置。如果您希望发布带有代码示例的答案,我会尝试并(可能)接受它。谢谢。

标签: ajax twitter-bootstrap angularjs lazy-loading


【解决方案1】:

这已经很老了,但问题可能仍然会不时出现。我现在发现这是最合适的解决方案,不会污染您的控制器: (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 手风琴组将只加载相应的指令。

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

【讨论】:

    【解决方案2】:

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

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

    我创建了一个小指令来绑定手风琴面板的点击事件。当点击事件被触发时,我通过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>
    

    【讨论】:

    • 这是一个很好的解决方案。感谢您花时间为我创建它。
    • 这是一个很好的解决方案,甚至适用于基础手风琴。感谢分享这个。对于那些对角度基础解决方案感兴趣的人,我正在分享这个 plunker:plnkr.co/edit/KkZlqs3UDdYE0805DTm9?p=preview
    猜你喜欢
    • 2021-05-20
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    • 2015-11-25
    相关资源
    最近更新 更多