【问题标题】:How to make a list and grid view toggle switch control that loads in partials in AngularJS?如何制作在AngularJS中加载的列表和网格视图切换控件?
【发布时间】:2014-04-22 06:58:57
【问题描述】:

我是 AngularJS 的新手,我一直无法找到加载两个不同 HTML 部分的列表和网格视图切换按钮的具体教程。阅读官方ng-includeng-switch官方文档并搜索SO。不幸的是,我们不想使用UI-router

加载两个部分(list.htmlgrid.html)是正确的 Angular 编码方式吗?


我找到的最相关的帮助如下:

1.http://tutorialzine.com/2013/08/learn-angularjs-5-examples(示例#5)

对示例 #5 有一个有见地的评论:

不错的简单示例 - 做得很好。 最后一个在网格视图和列表视图之间切换的例子不是很 高效,因为它同时创建选项和显示/隐藏选项。一种 更简单/更好的方法是使用带有中继器的单个 ul 和 ng-switch,然后使用启用备用列表元素 ng-开关盒。 - 约翰

2.http://www.adobe.com/devnet/html5/articles/getting-started-with-angularjs.html

3.https://stackoverflow.com/questions/12577378/create-a-single-html-view-for-multiple-partial-views-in-angularjs/12584774#12584774

4.https://stackoverflow.com/questions/15974086/conditional-ng-include-in-angularjs


我的 HTML 代码

<div class="col-xs-6" ng-controller="ToggleDisplayCtrl">
  <div class="btn-group select-format-container" ng-switch on="selected">
    <button ng-switch-when="true" ng-click="toggleGrid()" type="button"
      class="btn btn-primary" ng-model="formatChoice" ng-disabled="">grid</button>
    <button ng-switch-when="false" ng-click="toggleList()" type="button"
      class="btn btn-primary" ng-model="formatChoice" ng-disabled="">list</button>
  </div>
  <div ng-include src="formatChoice.url" scope="" onload=""></div>
</div>
<!-- col-xs-6  END ToggleDisplayCtrl-->

我的 JS 代码

'use strict';
var app = angular.module('tempApp');

app.controller('ToggleDisplayCtrl', function($scope) {
  $scope.formatChoices = [{
      name: 'grid',
      url: 'partials/grid.html'
    },
    {
      name: 'list',
      url: 'partials/list.html'
    }
  ];

  $scope.selected = true;
  $scope.toggleGrid = function() {
    if (selected) {
      return "partials/grid.html";
    }
    return "main.html";
  };
  $scope.toggleList = function() {
    if (selected) {
      return "partials/list.html";
    }
    return "main.html";
  };
});

【问题讨论】:

    标签: javascript angularjs listview gridview angularjs-ng-include


    【解决方案1】:

    您应该定义应用程序控制器的范围属性,该属性将保存ng-include 的模板 URL,并将此属性绑定到指令的范围。确保在指令中使用隔离作用域,以避免在修改指令作用域时产生副作用。下面是一个例子(见代码中的 cmets):

    JavaScript

    angular.module('app', ['ngRoute'])
      .config(['$routeProvider', function($routeProvider) {
        $routeProvider
          .when('/main', {
            controller: 'appController',
            templateUrl: 'main.html'
          })
          .otherwise({
            redirectTo: '/main'
          });
      }])
      .controller('appController', ['$scope', function($scope) {
        $scope.view = 'list.html'; // <- default template used for ng-include
        $scope.data = [{
          text: '1'
        }, {
          text: '2'
        }, {
          text: '3'
        }, {
          text: '4'
        }, {
          text: '5'
        }, {
          text: '6'
        }];
      }])
      .directive('appView', function() {
        return {
          scope: {
            // link view property of directive's scope to some property
            // in the parent scope (scope of appController) specified in
            // app-view attribute of root element of directive
            view: '=appView'
          },
          replace: true,
          template:
            '<nav class="navbar navbar-default">' +
              '<div class="container">' +
                '<ul class="nav navbar-nav navbar-right">' +
                  '<li ng-repeat="v in views" ng-bind="v.name" ' +
                      'ng-class="v.icon" ng-click="switchView(v)"></li>' +
                '</ul>' +
              '</div>' +
            '</nav>',
          link: function(scope, el, attr) {
            scope.views = [{
              name: 'List',
              template: 'list.html',
              icon: 'btn btn-default navbar-btn glyphicon glyphicon-th-list'
            }, {
              name: 'Grid',
              template: 'grid.html',
              icon: 'btn btn-default navbar-btn glyphicon glyphicon-th'
            }];
          },
          controller: ['$scope', function($scope) {
            $scope.switchView = function(view) {
              $scope.view = view.template; // <- modify parent scope view
            }
          }]
        }
      });
    

    应用程序主页(index.html)

    <html ng-app="app">
      ...
      <body ng-view=""></body>
    </html>
    

    路由模板 (main.html)

    <header app-view="view"></header>
    <section ng-include="view"></section>
    

    列表视图模板 (list.html)

    <div class="container">
      <div class="row">
        <div class="col-md-12 col-sm-12 panel panel-default" ng-repeat="item in data">
          <div class="panel-body">{{item.text}}</div>
        </div>
      </div>
    </div>
    

    网格视图模板 (grid.html)

    <div class="container">
      <div class="row">
        <div class="col-md-4 col-sm-6 panel panel-default" ng-repeat="item in data">
          <div class="panel-body">{{item.text}}</div>
        </div>
      </div>
    </div>
    

    Plunker:http://plnkr.co/edit/uWw7NuPG0I161mHXZg2r?p=preview

    奖励:网格是响应式的,只需使用窗口大小播放一下

    另一种选择:

    您可能已经注意到,grid.htmllist.html 非常相似,因此如果您只有这两个选项,您可能决定不使用带有单独可切换视图的 ng-include,而是将内容视图直接放入您的路线模板,只需使用ng-class 指令切换面板中使用的类,该指令可以在视图更改时切换类。

    路由模板 (main.html)

    <header app-view="view"></header>
    <section>
      <div class="container">
        <div class="row">
          <div ng-class="{'col-md-4': view === 'grid.html',
                          'col-md-12': view === 'list.html',
                          'panel':true, 'panel-default':true}"
               ng-repeat="item in data">
            <div class="panel-body">{{item.text}}</div>
          </div>
        </div>
      </div>
    </section>
    

    【讨论】:

    • 感谢您的精彩回答。我花了一段时间才明白。将其修改为使用&lt;button&gt;
    • 如果没有使用ng-repeat,我可以为每个按钮添加一个不同的ng-disabled=""。我如何将ng-disabled 合并到ng-repeat 中?我想显示按钮(和视图)被点击,即使我点击了按钮。
    • 您可以在使用ng-disabled 时使用控制器的$scope 中定义的函数ng-repeat,将一些值作为参数传递并从该函数返回布尔值。这是一个例子:plnkr.co/edit/EAenS3lZGVdSgWPH4aWc?p=preview如果您需要更详细的答案,请在 SO 上发布另一个问题并在评论中添加指向它的链接。
    【解决方案2】:

    基本上,您需要做的是在同一页面上同时放置一个列表视图和网格,并一次显示一个,使用切换按钮在它们之间切换(更改 css 类)。我将在这里讨论示例 #5:

    范围内的第一个布局变量:

    $scope.layout = 'grid';
    

    这里是开关按钮:

    <!-- On click change "$scope.layout = list" and if layout=='list' add class 'active' to self-->
    <a href="#" class="list-icon" ng-class="{active: layout == 'list'}" ng-click="layout = 'list'"></a>
    
    <!-- On click change "$scope.layout = grid" and if layout=='grid' add class 'active' to self-->
    <a href="#" class="grid-icon" ng-class="{active: layout == 'grid'}" ng-click="layout = 'grid'"></a>
    

    这些是网格和列表块:

    <!-- Layout=='grid' if layout parameter is grid than show this block -->
    <ul ng-show="layout == 'grid'" class="grid">...</ul>
    
    <!-- Layout=='list' if layout parameter is list than show this block -->
    <ul ng-show="layout == 'list'" class="list">...</ul>
    

    制作列表和网格布局的Css:

    /*-------------------------
      List layout
    --------------------------*/
    
    ul.list {
      list-style: none;
      width: 500px;
      margin: 0 auto;
      text-align: left;
    }
    
    ul.list li {
      border-bottom: 1px solid #ddd;
      padding: 10px;
      overflow: hidden;
    }
    
    ul.list li img {
      width: 120px;
      height: 120px;
      float: left;
      border: none;
    }
    
    ul.list li p {
      margin-left: 135px;
      font-weight: bold;
      color: #6e7a7f;
    }
    
    /*-------------------------
      Grid layout
    --------------------------*/
    
    ul.grid {
      list-style: none;
      width: 570px;
      margin: 0 auto;
      text-align: left;
    }
    
    ul.grid li {
      padding: 2px;
      float: left;
    }
    
    ul.grid li img {
      width: 280px;
      height: 280px;
      display: block;
      border: none;
    }
    

    【讨论】:

      【解决方案3】:

      最简单的方法是:

      <div class="bar">
        <h1>Contacts</h1>
        <a href="#" class="list-icon" ng-class="{active: layout == 'list'}" ng-click="layout = 'list'"></a>
        <a href="#" class="grid-icon" ng-class="{active: layout == 'grid'}" ng-click="layout = 'grid'"></a>
      </div>
      <div ng-show="layout == 'list'" class="list">
      <!-- Add your list page here -->
      <div ng-show="layout == 'grid'" class="grid">
      <!-- Add your grid page here -->
      

      CSS:

      /*
        Contacts bar with toggle switches
      */
      
      .bar {
        background-color: #5c9bb7;
        background-size: 100% 100%;
        box-shadow: 0 1px 1px #ccc;
        border-radius: 2px;
        height: 100px;
        padding: 10px;
        position: relative;
        text-align: right;
        line-height: 1;
      }
      
      .bar a {
        background: #4987a1 center center no-repeat;
        width: 32px;
        height: 32px;
        display: inline-block;
        text-decoration: none !important;
        margin-right: 5px;
        border-radius: 2px;
      }
      
      .bar a.active {
        background-color: #c14694;
      }
      
      .bar a.list-icon {
        background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkYzNkFCQ0ZBMTBCRTExRTM5NDk4RDFEM0E5RkQ1NEZCIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkYzNkFCQ0ZCMTBCRTExRTM5NDk4RDFEM0E5RkQ1NEZCIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6RjM2QUJDRjgxMEJFMTFFMzk0OThEMUQzQTlGRDU0RkIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RjM2QUJDRjkxMEJFMTFFMzk0OThEMUQzQTlGRDU0RkIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7h1bLqAAAAWUlEQVR42mL8////BwYGBn4GCACxBRlIAIxAA/4jaXoPEkMyjJ+A/g9MDJQBRhYg8RFqMwg8RJIUINYLFDmBUi+ADQAF1n8ofk9yIAy6WPg4GgtDMRYAAgwAdLYwLAoIwPgAAAAASUVORK5CYII=);
      }
      
      .bar a.grid-icon {
        background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjBEQkMyQzE0MTBCRjExRTNBMDlGRTYyOTlBNDdCN0I4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjBEQkMyQzE1MTBCRjExRTNBMDlGRTYyOTlBNDdCN0I4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MERCQzJDMTIxMEJGMTFFM0EwOUZFNjI5OUE0N0I3QjgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MERCQzJDMTMxMEJGMTFFM0EwOUZFNjI5OUE0N0I3QjgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4MjPshAAAAXklEQVR42mL4////h/8I8B6IGaCYKHFGEMnAwCDIAAHvgZgRyiZKnImBQsACxB+hNoDAQyQ5osQZIT4gH1DsBZABH6AB8x/JaQzEig++WPiII7Rxio/GwmCIBYAAAwAwVIzMp1R0aQAAAABJRU5ErkJggg==);
      }
      
      /*-------------------------
        List layout
      --------------------------*/
      
      ul.list {
        list-style: none;
        width: 500px;
        margin: 0 auto;
        text-align: left;
      }
      
      ul.list li {
        border-bottom: 1px solid #ddd;
        padding: 10px;
        overflow: hidden;
      }
      
      ul.list li img {
        width: 120px;
        height: 120px;
        float: left;
        border: none;
      }
      
      ul.list li p {
        margin-left: 135px;
        font-weight: bold;
        color: #6e7a7f;
      }
      
      /*-------------------------
        Grid layout
      --------------------------*/
      
      ul.grid {
        list-style: none;
        width: 570px;
        margin: 0 auto;
        text-align: left;
      }
      
      ul.grid li {
        padding: 2px;
        float: left;
      }
      
      ul.grid li img {
        width: 280px;
        height: 280px;
        display: block;
        border: none;
      }
      

      【讨论】:

        【解决方案4】:

        这是一个简单的工作 JSBin:http://jsbin.com/jomiquqi/1/edit

        ng-include 指令接受一个变量供模板包含。因此,要更新您的代码以使其正常工作,您的 toggleGrid() 方法不应返回任何内容,它应该在传递给 ng-include 的范围内设置一个变量,就像我的示例中一样。

        【讨论】:

        • 我需要外部 HTML 内容,而不是内联。谢谢你教我ng-template
        • 这不是问题。我使用内联模板只是因为这样制作示例更简单。就像我的例子一样,但将模板路径更改为您的真实路径。
        • 我以为ng-template 只能使用内联HTML。如何将模板路径更改为外部 HTML 文件?
        • 您不必更改任何内容,只需将其指向模板的 url,就像在您的路由或指令中一样。
        【解决方案5】:

        为了更好地理解切换操作以查看列表和网格视图: follow this link 我希望这会有所帮助。

        如果您正在对此进行试验,我们使用了 Jquery。做这个: &lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"&gt;&lt;/script&gt;

        【讨论】:

          【解决方案6】:

          一个简单的轻量级解决方案,它是使用 AngularJS Material 库构建的,没有任何指令。当用户点击listView时,容器的布局变为不换行的column,当用户点击gridView时,容器的布局变为带换行的row

          'use strict';
          const application = angular.module("application", ['ngMaterial']);
          application.controller('applicationCtrl', ['$scope', function(scope) {
            scope.toggleGridList = function(newValue) {
              if (newValue === "gridView") {
                scope.value = 'gridView';
                scope.layout = 'row';
              } else {
                scope.value = 'listView';
                scope.layout = 'column';
              }
            };
            scope.onInit = function() {
              scope.toggleGridList('listView');
            };
          }]);
          .grid-list-toggle {
            padding: 0 !important;
            margin: 8px;
            border-radius: 2px;
            border: 1px solid #c8e6c9;
          }
          
          .grid-list-button {
            margin: 0 !important;
            min-width: 0 !important;
            min-height: 0 !important;
            border-radius: 0 !important;
          }
          
          .grid-list-button.selected {
            background-color: #c8e6c9;
          }
          <head>
            <link rel="stylesheet" href="https://material.angularjs.org/1.1.24/angular-material.min.css">
            <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.0/angular.min.js"></script>
            <script src="https://code.angularjs.org/1.8.0/angular-animate.min.js"></script>
            <script src="https://code.angularjs.org/1.8.0/angular-aria.min.js"></script>
            <script src="https://material.angularjs.org/1.1.24/angular-material.min.js"></script>
          </head>
          
          <body ng-app="application" ng-controller="applicationCtrl"
                ng-init="onInit();" class="ng-cloak" style="overflow: hidden;">
            <!-- Header -->
            <div layout="row" md-whiteframe="1" layout-align="start center">
              <!-- Title -->
              <div layout-padding>
                <span class="md-display-1" style="color: #1b5e20;">Grid-list toggle button</span>
              </div>
              <!-- Divider -->
              <div flex></div>
              <!-- Grid-list toggle button -->
              <div layout="row" layout-padding class="grid-list-toggle">
                <md-button class="grid-list-button" ng-click="toggleGridList('listView')"
                    aria-label="List" ng-class="value == 'listView' ? 'selected' : ''">
                  <div style="height: 30px">
                    <img src="https://i.stack.imgur.com/SOqYv.png">
                  </div>
                </md-button>
                <md-button class="grid-list-button" ng-click="toggleGridList('gridView')"
                    aria-label="Grid" ng-class="value == 'gridView' ? 'selected' : ''">
                  <div style="height: 30px">
                    <img src="https://i.stack.imgur.com/STQJn.png">
                  </div>
                </md-button>
              </div>
            </div>
            <!-- Page content -->
            <div flex="100" layout="column" md-whiteframe="1">
              <div layout="{{layout}}" layout-padding style="overflow-y: auto;"
                  ng-class="value == 'gridView' ? 'layout-wrap' : 'layout-nowrap'">
                <div layout="row" layout-padding layout-align="start center" class="grid-list-toggle"
                    ng-repeat="number in [].constructor(10) track by $index">
                  <img src="https://i.stack.imgur.com/WANVK.png">
                  <div layout="column">
                    <span>Title {{$index}}</span>
                    <span>Description</span>
                    <span>Another line</span>
                  </div>
                </div>
              </div>
            </div>
          </body>

          参见:«Grid-list toggle button»。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-04-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-15
            相关资源
            最近更新 更多