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

Using *ngFor in CSS Grid Layout Undesirably Displaying Everything in One Column

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

我想将方框放入 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" alt="pic-test" >
        <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" alt="pic-test" >
        <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" alt="pic-test" >
        <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" alt="pic-test" >
        <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" alt="pic-test" >
        <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" alt="pic-test" >
        <p>more text here.</p>
        <p>{{s.title}}</p>
    </div>
</div>

我的解决方法是...让这个 div 元素 4 次,其中 i 在 *ngIf(i+1、i+2 等)上递增 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" alt="pic-test" >
      <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" alt="pic-test" >
      <p>more text here.</p>
      <p>{{stickyNotes[i+1].title}}</p>
</div>

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

我想知道是否有一种方法可以在不破坏网格 属性 并且无需将 item2 class 编码 4 次(或任何其他方法)的情况下创建自定义可迭代指令。

我尝试了 bootstrap 行和列属性,但是对于 4 列,响应不如网格布局好。

如有任何帮助或建议,我们将不胜感激!

试试这个语法:

<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" alt="pic-test">
      <p>more text here.</p>
      <p>{{s.title}}</p>
    </div>
  </ng-container>
</div>

*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" alt="pic-test" >
        <p>more text here.</p>
        <p>{{s.title}}</p>
   </div>
</div>

Vega 提供的答案也可以,但是 <ng-container> 不是必需的(只要您不输入另一个 structural directive on the div.item2element), because asterisk is only syntactic sugar and expands to 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" alt="pic-test" >
      <p>more text here.</p>
      <p>{{s.title}}</p>
    </div>
  </ng-template>
</div>

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

Someday you'll want to repeat a block of HTML but only when a particular condition is true. You'll try to put both an *ngFor and an *ngIf on the same host element. Angular won't let you. You may apply only one structural directive to an element.

The reason is simplicity. Structural directives can do complex things with the host element and its descendents. When two directives lay claim to the same host element, which one takes precedence? Which should go first, the NgIf or the NgFor? Can the NgIf cancel the effect of the NgFor? If so (and it seems like it should be so), how should Angular generalize the ability to cancel for other structural directives?

There are no easy answers to these questions. Prohibiting multiple structural directives makes them moot. There's an easy solution for this use case: put the *ngIf on a container element that wraps the *ngFor element. One or both elements can be an ng-container so you don't have to introduce extra levels of HTML.