【问题标题】:Angular Mat-List-Option Layout Changes When Using CDK Drag and Drop使用 CDK 拖放时 Angular Mat-List-Option 布局更改
【发布时间】:2019-10-07 21:30:48
【问题描述】:

我正在开发一个 Angular 7 Web 应用程序,并且正在努力使用 Mat-Selection-List,我允许用户拖放 mat-list-option 项目。

每个mat-list-option 项目都包含一个div,它使用Flex Layout 来排列其组件,如下所示:

          <mat-selection-list #taskGroupSelectionList
                              cdkDropList
                              [(ngModel)]="selectedOptions"
                              (ngModelChange)="onNgModelChange($event)"
                              (selectionChange)="onSelectionChange($event)"
                              class="task-group-list"
                              (cdkDropListDropped)="drop($event)">

            <mat-list-option class="task-group-box" checkboxPosition="after" *ngFor="let taskGroup of taskGroups" [value]="taskGroup" cdkDrag>

              <!-- Task Group Item -->
              <div fxLayout="row" *ngIf="taskGroup" fxLayoutAlign="start center" style="width: 100%; height: 100%;">

                <!-- Move Handle -->
                <div fxFlex="32px" style="padding: 0 0 0 4px;">
                  <mat-icon class="summary-channel-handle">menu</mat-icon>
                </div>

                <!-- Index -->
                <div fxFlex="24px;">
                  <p style="margin: 0; text-align: right;">
                    {{taskGroup.orderId}}:
                  </p>
                </div>

                <!-- Title -->
                <div fxFlex="nogrow">
                  <p style="margin: 0; padding: 0 0 0 8px; text-overflow: ellipsis; white-space: nowrap;">
                    {{taskGroup.title}}
                  </p>
                </div>

              </div>

            </mat-list-option>

          </mat-selection-list>

这个简单组件的关键 CSS 样式如下:

.task-group-list {
  width: 100%;
  height: 100%;
  display: block;
  background: white;
}

.task-group-box {
  border-left: solid 1px #ddd;
  border-right: solid 1px #ddd;
  border-bottom: solid 1px #ddd;
  border-radius: 4px;
  height: 48px;
  color: rgba(0, 0, 0, 0.87);
  box-sizing: border-box;
  cursor: move;
  background: white;
}

.task-group-box:first-child {
  border: solid 1px #ddd;
}

.task-group-list.cdk-drop-list-dragging .task-group-box:not(.cdk-drag-placeholder) {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

.cdk-drag-preview {
  box-sizing: border-box;
  border-radius: 4px;
  height: 48px;
  box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
}

.cdk-drag-placeholder {
  box-sizing: border-box;
  border-radius: 4px;
  height: 48px;
  opacity: 0;
}

.cdk-drag-animating {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

功能上我可以拖放列表项,但是在拖动时,我放置在右侧的mat-list-option 复选框checkboxPosition="after" 移动到左上角并将mat-list-option 的元素向下推。

有谁知道为什么拖动时布局会发生变化?

【问题讨论】:

    标签: angular-material


    【解决方案1】:

    被拖动的元素可以在 DOM 中作为 body 的最后一个子元素找到(仅在拖动时),这会产生一些问题,您可以阅读 here

    如果你的 mat-list-option 元素不是很复杂,只有复选框和一些文本,你可以通过在全局 styles.css 文件中添加一些 CSS 来解决这个问题,例如:

    /* Checkbox and text inline and vertically centered */
    .cdk-drag-preview .mat-list-item-content {
        display: flex;
        align-items: center;
    }
    
    /* Checkbox margin from text */
    .cdk-drag-preview .mat-pseudo-checkbox {
      margin-right: 10px;
    }
    

    你可以在我创建的这个 stackblitz 中看到 DEMO

    如果你的 mat-list-option 元素的内容有点复杂,你需要检查元素并添加必要的样式。您可以通过拖动 mat-list-option 并在拖动时右键单击来执行此操作,检查元素并找到可用于设置样式的类。

    【讨论】:

    • 这就是答案,应该标记为已接受。
    【解决方案2】:

    试试 ::ng-deep

    ::ng-deep .cdk-drag-preview  .mat-list-item-content{
        display: flex;
        flex-direction: row;
        align-items: center;
        box-sizing: border-box;
        padding: 0 16px;
        position: relative;
        height: inherit;
      }
    

    这对我有用

    【讨论】:

      【解决方案3】:

      更好的选择可能是只创建一个custom cdkDragPreview。您可以根据需要设置此样式。

      <mat-selection-list #movies cdkDropList>
      
        <mat-list-option *ngFor="let movie of movies" cdkDrag>
      
          {{movie}}
      
          <ng-template cdkDragPreview [matchSize]="true">
            <div class="movie-preview">
                {{ movie }}
            </div>
          </ng-template>
        
        </mat-list-option>
      
      </mat-selection-list>
      

      重要提示:需要 ma​​tchSize 输入来自动调整被拖动项目的大小。

      而且由于 css 的范围仅限于您的组件,因此即使将其移到组件的 DOM 树之外,它也会保留样式(假设为模拟样式封装)。

      .movie-preview
      {
          line-height: 3;
          padding: 0 1em;
          color: hotpink;
          background: white;
      
          /* border (and hotpink color) are optional, based on your preference */
          border: 1px solid #ccc;   
          border-radius: .5em;
      }
      

      拖动时是这样的:

      【讨论】:

        猜你喜欢
        • 2019-04-25
        • 1970-01-01
        • 2020-07-15
        • 2019-05-05
        • 2020-09-25
        • 1970-01-01
        • 1970-01-01
        • 2023-03-21
        • 1970-01-01
        相关资源
        最近更新 更多