在 CSS 网格布局中使用 *ngFor 不希望地在一列中显示所有内容

Posted

技术标签:

【中文标题】在 CSS 网格布局中使用 *ngFor 不希望地在一列中显示所有内容【英文标题】:Using *ngFor in CSS Grid Layout Undesirably Displaying Everything in One Column 【发布时间】:2018-02-21 05:49:34 【问题描述】:

总的来说,我是编程和网络开发的新手。我正在制作个人网站。

我想将框放在一个有 4 列的网格中,类似于您在此处看到的:https://devpost.com/software/search?query=is%3Afeatured

这些框中的每一个都代表一个对象,我希望能够在框内显示一些数据,而当您单击框时,将其余数据显示在弹出对话框中。

我一直在玩 CSS 网格布局,现在它变得很流行(强烈推荐这个视频:https://www.youtube.com/watch?v=7kVeCqQCxlk)。

当我在包装器 div 中对一堆 div 元素进行硬编码时,具有 4 列的东西会起作用。但是,每当我在包含我的数据数组的包装器上使用 *ngFor 并将每次迭代中的数据输入到内部 div 元素时,网格布局都会被破坏,将所有内容放入一列中。

当我使用多个 div 元素(此处为 item2)手动输入数据时,它会按需要工作:

.wrapper 
    margin-left: 1em;
    margin-right: 1em;
    display: grid;
    grid-template-rows: auto;
    grid-template-columns: repeat(4, 1fr);
    grid-row-gap: 1em;
    grid-column-gap: 1em;
<div class="wrapper">

    <div class="item2" style="background-color: deepskyblue;">
        <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png"  >
        <p>more text here.</p>
    </div>

    <div class="item2" style="background-color: deepskyblue;">
        <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png"  >
        <p>more text here.</p>
    </div>

    <div class="item2" style="background-color: deepskyblue;">
        <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png"  >
        <p>more text here.</p>
    </div>

    <div class="item2" style="background-color: deepskyblue;">
        <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png"  >
        <p>more text here.</p>
    </div>

    <div class="item2" style="background-color: deepskyblue;">
        <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png"  >
        <p>more text here.</p>
    </div>
    
</div>

使用 *ngFor... 它运行数组“stickyNotes”的长度,但仅在每行下方堆叠框。

<div class="wrapper" *ngFor="let s of stickyNotes; let i = index" >
    <div class="item2" style="background-color: deepskyblue;">
        <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png"  >
        <p>more text here.</p>
        <p>s.title</p>
    </div>
</div>

我对此的破解是...在 *ngIf(i+1、i+2 等)上将这个 div 元素添加 4 次,其中 i 增加 1。这里的问题是,当新行开始时,CSS 中的 grid-row-gap 会被忽略。

<div class="item2" style="background-color: deepskyblue;" *ngIf="i < stickyNotes.length && i%4 === 0">
      <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png"  >
      <p>more text here.</p>
      <p>stickyNotes[i].title</p>
</div>

<div class="item2" style="background-color: deepskyblue;" *ngIf="i+1 < stickyNotes.length && i%4 === 0">
      <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png"  >
      <p>more text here.</p>
      <p>stickyNotes[i+1].title</p>
</div>

<!--2 more times until i+3-->

我想知道是否有一种方法可以创建自定义可迭代指令,而不会破坏网格属性,也无需将 item2 类编码 4 次(或任何其他方法)。

我尝试过引导行和列属性,但是有 4 列,响应性不如网格布局。

任何帮助或建议将不胜感激!

【问题讨论】:

【参考方案1】:

*ngFor 重复你添加它的元素。只需将它放在div.item2 上,它应该可以工作:

<div class="wrapper" >
    <div class="item2" *ngFor="let s of stickyNotes; let i = index" style="background-color: deepskyblue;" >
        <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png"  >
        <p>more text here.</p>
        <p>s.title</p>
   </div>
</div>

Vega 提供的答案也可以,但&lt;ng-container&gt; 不是必需的(只要您不在div.item2 元素上添加另一个structural directive),因为星号只是语法糖并扩展为something similar:

<div class="wrapper" >
  <ng-template ngFor let-s [ngForOf]="stickyNotes" let-i="index">
    <div class="item2" style="background-color: deepskyblue;">
      <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png"  >
      <p>more text here.</p>
      <p>s.title</p>
    </div>
  </ng-template>
</div>

每个元素一个结构指令的限制背后的原因是given here:

有一天,您会想要重复一段 html,但前提是特定条件为真。您将尝试将 *ngFor 和 *ngIf 放在同一个宿主元素上。 Angular不会让你。您只能将一个结构指令应用于一个元素。

原因是简单。结构指令可以对宿主元素及其后代做复杂的事情。当两个指令声明同一个宿主元素时,哪一个优先? NgIf 或 NgFor 应该先走哪一个? NgIf 可以取消 NgFor 的效果吗?如果是这样(看起来应该是这样),Angular 应该如何概括取消其他结构指令的能力?

这些问题没有简单的答案。禁止多个结构性指令使它们没有实际意义。这个用例有一个简单的解决方案:将 *ngIf 放在包装 *ngFor 元素的容器元素上。一个或两个元素都可以是 ng 容器,因此您不必引入额外的 HTML 级别。

【讨论】:

效果很好。太感谢了!!无法在 div 元素上放置结构指令的原因是什么? 我想说的是,你不能将两个结构指令放在一个元素上。我会编辑我的答案【参考方案2】:

试试这个语法:

<div class="wrapper">
  <ng-container *ngFor="let s of stickyNotes; let i = index">
    <div class="item2" style="background-color: deepskyblue;">
      <img class="img-responsive img-rounded" src="assets/Logo/square_filler.png" >
      <p>more text here.</p>
      <p>s.title</p>
    </div>
  </ng-container>
</div>

【讨论】:

这个也可以!没想到这么简单...谢谢!

以上是关于在 CSS 网格布局中使用 *ngFor 不希望地在一列中显示所有内容的主要内容,如果未能解决你的问题,请参考以下文章

CSS 网格布局和 nth-child

响应式网格(栅格化)布局总结

在 CSS 网格布局中为每一列添加滚动

CSS进阶之关于网格布局(Grid) 你了解哪些

CSS进阶之关于网格布局(Grid) 你了解哪些

任务八:响应式网格(栅格化)布局