【问题标题】:How to add multiple ng-repeats inside a ng-repeat?如何在 ng-repeat 中添加多个 ng-repeat?
【发布时间】:2017-07-24 10:13:32
【问题描述】:

好的,我正在处理一些具有挑战性的网格,需要一些帮助。 我需要找到一种通过 ng-repeat 填充数据的方法。我将附上我正在尝试实现的网格布局的图像以及应填充的数据顺序。我已经通过以下方法在 HTML 中完成了布局。但是通过 ng-repeat 找不到方法。

ROW 1 - 正常引导 col-md-4 和 col-md-8

ROW 2 - 我使用 CSS3 Flexbox 完成了这一行。你可以看看下面的代码。

ROW 3 - 正常引导 col-md-4 和 col-md-8

This 是我一直在尝试做的事情。 [https://plnkr.co/edit/NtXEnQcKpM0JxnLsxc4m?p=preview]2

我也会尝试传达这背后的逻辑。 所以在网格的底部会有一个加载更多按钮来再次重复整个布局并填充数据。因此,我计划在容器上放置和 ng-repeat。在此之后,我将布局分为 3 行。 - 第一个由第 1 列和第 2 列组成 - 第二行由第 3 到 7 列组成 - 第三行由第 8 列和第 9 列组成

返回的数组也以同样的方式划分。

如果我的方法是错误的,我希望我能弄清楚,也许是实现这种布局的解决方法。

【问题讨论】:

  • 你看过ng-repeat-start和ng-repeat-end吗?
  • 我刚刚开始使用 AngularJS。我会看看这个。感谢您的意见。
  • 这是一个工作小提琴,而不是你坏掉的 plunkr 来显示重复工作:jsfiddle.net/93sozhkf
  • 您是否以您概述的格式设置了数据 json?还是不必将您的数据“预先分组”成行?而是能够只提供一个列表来为每组 9 个元素生成设计?

标签: javascript angularjs twitter-bootstrap css angularjs-ng-repeat


【解决方案1】:

要制作您概述的设计,我建议执行以下操作:

  1. 使用过滤器将您的文章“分块”成 9 个一组(类似于 memoized chunking solution)

  2. 使用自定义指令创建您的“模板”

  3. 利用响应式固定比例网格系统(例如 cough 我的图书馆 Perfect Bootstrap cough)

Example JSFiddle


步骤1

让我们将您的 JSON 放回标准数组,然后在运行时将其“分块”成 9 个批次。我们创建一个角度filter,然后使用 | chunk 应用它。为了避免无限的摘要循环,我们需要使用变量来记忆函数的结果,在下面的代码中,我们使用字符串'newsGroups'。如果您打算将更多项目加载到数组中,例如无限滚动,则需要更新此变量以刷新记忆结果。把它想象成一个缓存中断。

为简洁起见,我已将您的文章数组剥离为每个元素的 id 和 title 项目。无论如何,我会假设这是来自您的开发环境中的 AJAX 调用。

HTML

<div class="container-fluid" ng-controller="MyCtrl">
  <div class="template-container" ng-repeat="newsGroup in NewsListing | chunk:'newsGroups'">
    <!-- content here -->
  </div>
</div>

JS Chunk 过滤器和文章的基本数组

var myApp = angular.module('myApp', []);
myApp.filter('chunk', function() {
  function cacheIt(func) {
    cache = {};
    return function(arg) {
      // if the function has been called with the argument
      // short circuit and use cached value, otherwise call the
      // cached function with the argument and save it to the cache as well then return
      return cache[arg] ? cache[arg] : cache[arg] = func(arg);
    };
  }

  // unchanged from your example apart from we are no longer directly returning this
  function chunk(items, chunk_size) {
    var chunks = [];
    if (angular.isArray(items)) {
      if (isNaN(chunk_size))
        chunk_size = 9;
      for (var i = 0; i < items.length; i += chunk_size) {
        chunks.push(items.slice(i, i + chunk_size));
      }
    } else {
      console.log("items is not an array: " + angular.toJson(items));
    }
    return chunks;
  }
  // now we return the cached or memoized version of our chunk function
  // if you want to use lodash this is really easy since there is already a chunk and memoize function all above code would be removed
  // this return would simply be: return _.memoize(_.chunk);

  return cacheIt(chunk);
});
myApp.controller('MyCtrl', function($scope) {
  $scope.NewsListing = [{
    "id": "71b85130-ffe4-11e6-81a4-c1bd97df0d2d",
    "title": "Exercitation ullamco laboris"
  }, {
    "id": "58847180-ffe4-11e6-81a4-c1bd97df0d2d",
    "title": "Duis aute irure dolor in reprehenderit"
  }, {
    "id": "35d2c290-ffe4-11e6-81a4-c1bd97df0d2d",
    "title": "Ut enim ad minim"
  }, {
    "id": "fdbdeb00-ffe3-11e6-81a4-c1bd97df0d2d",
    "title": "Ut enim ad minim"
  }, {
    "id": "df858f30-ffe3-11e6-81a4-c1bd97df0d2d",
    "title": "Dolore magna aliqua"
  }, {
    "id": "bbc619c0-ffe3-11e6-81a4-c1bd97df0d2d",
    "title": "Qui officia deserunt mollit anim"
  }, {
    "id": "8467e800-ffe3-11e6-81a4-c1bd97df0d2d",
    "title": "Consectetur adipisicing elit, sed do eiusm"
  }, {
    "id": "5aea9180-ffe3-11e6-81a4-c1bd97df0d2d",
    "title": "Lorem elit, sed do eiusm"
  }, {
    "id": "418d09c0-ffe3-11e6-81a4-c1bd97df0d2d",
    "title": "ALL YOU NEED TO KNOW ABOUT WAREHOUSE"
  }, {
    "id": "71b85130-ffe4-11e6-81a4-c1bd97df0d2e",
    "title": "Exercitation ullamco laboris2"
  }, {
    "id": "58847180-ffe4-11e6-81a4-c1bd97df0d2e",
    "title": "Duis aute irure dolor in reprehenderit2"
  }, {
    "id": "35d2c290-ffe4-11e6-81a4-c1bd97df0d2e",
    "title": "Ut enim ad minim2"
  }, {
    "id": "fdbdeb00-ffe3-11e6-81a4-c1bd97df0d2e",
    "title": "Ut enim ad minim2"
  }, {
    "id": "df858f30-ffe3-11e6-81a4-c1bd97df0d2e",
    "title": "Dolore magna aliqua2"
  }, {
    "id": "bbc619c0-ffe3-11e6-81a4-c1bd97df0d2e",
    "title": "Qui officia deserunt mollit anim2"
  }, {
    "id": "8467e800-ffe3-11e6-81a4-c1bd97df0d2e",
    "title": "Consectetur adipisicing elit, sed do eiusm2"
  }, {
    "id": "5aea9180-ffe3-11e6-81a4-c1bd97df0d2e",
    "title": "Lorem elit, sed do eiusm2"
  }, {
    "id": "418d09c0-ffe3-11e6-81a4-c1bd97df0d2e",
    "title": "ALL YOU NEED TO KNOW ABOUT WAREHOUSE2"
  }];
})

第 2 步

在步骤 1 的 HTML 的 content here 注释部分中,我们将应用自定义指令。在实际开发中,我可能会使用单独的文件来保存模板,但是,对于 js fiddle 的约束,我需要将其定义为 text/ng-template script 标签。

您可以看到,第 1 步中 ng-repeat 中的 newsGroup 将使用范围值 items 传递给我们的自定义指令。这将包含最多 9 篇新闻文章。

HTML 指令调用

<div nine-item-news items="newsGroup"></div>

JS 指令定义

myApp.directive('nineItemNews', function() {
  return {
    restrict: 'A',
    replace: true,
    templateUrl: '/nine-item-news-template.html',
    scope: {
      items: '='
    }
  }
});

HTML 模板

<script type="text/ng-template" id="/nine-item-news-template.html">
<div class="template">
    <!-- template content here -->
</div>
</script>

第三步

不久前,我开发了一个 CSS 库,旨在提供响应式固定比例网格元素。这个问题促使我终于把它公之于众。可以把它想象成 bootstrap 的水平 col- 功能,但它是垂直的。

我们将上面的 template content here 注释替换为以下 html,它将加载由步骤 2 中的自定义指令传递给它的项目。我建议您扩展此模板以添加 ng-if 语句以加载/卸载块,同样,我建议使用ng-class 来调整设计,以适应您没有收到完整 9 件物品的情况(即,如果只传递 6 件物品会是什么样子)。或者,使用基于items.length 的ng-switch 并加载完全不同的模板也可以类似地工作。

额外的 CSS 是添加背景颜色并删除引导列的默认填充/边距。

注意:请注意,为了使元素保持它们的比例,它们的overflow 设置为hidden。这在项目具有背景图像时特别有效,但可能会对文本产生意想不到的后果。我的示例包括一个移动响应模板设计,它创建比例为 2:1 的部分。我鼓励您针对您的特定构建和一些屏幕分辨率仔细测试它。

HTML 模板内容

<div class="row" ng-if="items.length">
    <div class="col-xs-12 col-md-4 col-no-padding">
        <div class="row-xs-6 row-md-12">
            <div class="abs-inner bg-darkgrey">
                <p ng-bind="items[0].title"></p>
            </div>
        </div>
    </div>
    <div class="col-xs-12 col-md-8 col-no-padding">
        <div class="row-xs-6">
            <div class="abs-inner bg-grey">
                <p ng-bind="items[1].title"></p>
            </div>
        </div>
    </div>
</div>
<div class="row">
    <div class="col-xs-12 col-md-4 col-no-padding">
        <div class="row">
            <div class="col-xs-12 col-no-padding">
                <div class="row-xs-6">
                    <div class="abs-inner bg-grey">
                        <p ng-bind="items[2].title"></p>
                    </div>
                </div>
            </div>
            <div class="col-xs-12 col-no-padding">
                <div class="row-xs-6">
                    <div class="abs-inner bg-midgrey">
                        <p ng-bind="items[5].title"></p>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="col-xs-12 col-md-4 col-no-padding">
        <div class="row-xs-6 row-md-12">
            <div class="abs-inner bg-white">
                <p ng-bind="items[3].title"></p>
            </div>
        </div>
    </div>
    <div class="col-xs-12 col-md-4 col-no-padding">
        <div class="row">
            <div class="col-xs-12 col-no-padding">
                <div class="row-xs-6">
                    <div class="abs-inner bg-grey">
                        <p ng-bind="items[4].title"></p>
                    </div>
                </div>
            </div>
            <div class="col-xs-12 col-no-padding">
                <div class="row-xs-6">
                    <div class="abs-inner bg-midgrey">
                        <p ng-bind="items[6].title"></p>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<div class="row">
    <div class="col-xs-12 col-md-4 col-no-padding">
        <div class="row-xs-6 row-md-12">
            <div class="abs-inner bg-darkgrey">
                <p ng-bind="items[7].title"></p>
            </div>
        </div>
    </div>
    <div class="col-xs-12 col-md-8 col-no-padding">
        <div class="row-xs-6">
            <div class="abs-inner bg-grey">
                <p ng-bind="items[8].title"></p>
            </div>
        </div>
    </div>
</div>

CSS

.col-no-padding{
  padding-left:0;
  padding-right:0;
}
.col-no-padding > .row{
  margin-left:0;
  margin-right:0;
}
.bg-darkgrey{
  background-color:#535353;
}
.bg-midgrey{
  background-color:#808080;
}
.bg-grey{
  background-color:#959595;
}
.bg-lightgrey{
  background-color:#d0d0d0;
}
.bg-white{
  background-color:#FFFFFF;
}

【讨论】:

    【解决方案2】:

    我认为在 Angular 中执行此操作的正确方法应该是自定义指令。

    当用户loas更多时,应该再次出现一个整体布局,因此该指令应该显示整个布局。

    您只需在指令的参数中提供数据,根据需要显示它(例如在数组中提供数据或获取索引的东西)。

    我们称该指令为 layoutDirective。

    然后你把它放在你的 html 中:

    <div ng-repeat="array in arrays" ng-if="$index < limitDisplay">
      <layout-directive data=array> </layout-directive>
    </div>
    

    这里唯一的技巧是 ng-if 指令

    当有人按下 load 时,limitDisplay 是一个 int 增量更多 我不确定这样写的数据绑定,稍后我会尝试改进我的答案以帮助您创建一个好的指令

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-14
      • 2014-12-02
      • 1970-01-01
      • 2015-10-07
      • 2017-12-22
      • 2013-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多