【问题标题】:How to properly manage the "toggle" state of an Angular mat slide toggle?如何正确管理 Angular mat 滑动切换的“切换”状态?
【发布时间】:2020-11-10 00:21:12
【问题描述】:

我有一个表格,里面有一个滑动切换开关,它根据我从 API 返回的数据加载为切换/未切换。这按预期工作。然后,用户可以切换此开关,这会导致将 POST 请求发送到 API。如果此 POST 失败,我想将切换开关重置到它最初加载的任何位置。我正在尝试通过在失败时再次发出原始 observable 来尝试此操作。我已通过浏览器中的控制台验证,这为切换提供了我期望的值,但是滑块没有相应移动。

在这一点上,我质疑我是否以正确的方式进行此操作,因为切换位置似乎不受该值更改时绑定的值的影响。我注意到垫子滑动开关有一个内置的toggle() 方法,我应该调用它吗?我想知道管理滑动切换位置的正确方法,因为我找不到任何文档。

组件.ts

ngOnInit() {
    const lastItems$ = new ReplaySubject(1);

    const getItemsAndCache = () => {
      return this.myService
        .getItems(this.accountId)
        .pipe(
          tap(itemsRes => lastItems$.next([...itemsRes])
          )
        )
    };

    geItemsAndCache().subscribe(items => lastItems$.next(items));

    const updatedItems$ = this.itemChangeSubject.asObservable().pipe(
        exhaustMap(itemChange => 
        this.myService.changeItemToggle(
            this.accountId,
            itemChange.item.id
        )
        .pipe(
            mergeMap(() => getItemsAndCache()),
            catchError(() => lastItems$.pipe(first())
            ))
        )
    )

    this.items$ = concat(lastItems$.pipe(first()), updatedItems$) as Observable<MyItem[]>;

}

onToggleChange(item: MyItem) {
   this.itemChangeSubject.next({ item });

}

组件.html

<my--custom-table
[items]="items$ | async"
[displayedColumns]="displayedColumns"
[paginationOptions]="paginationOptions"
>
<ng-container matColumnDef="status">
  <mat-header-cell *matHeaderCellDef>Status</mat-header-cell>
  <mat-cell *matCellDef="let item">
    {{ item.status }}
  </mat-cell>
</ng-container>
<ng-container matColumnDef="toggled">
  <mat-header-cell *matHeaderCellDef>Toggled?</mat-header-cell>
  <mat-cell *matCellDef="let item">
    <span>{{item.toggled}}</span>
    <mat-slide-toggle
      [(ngModel)]="item.toggled"
      [disabled]="clicked"
      (change)="onToggleChange(item); clicked = true"
    ></mat-slide-toggle>
  </mat-cell>
</ng-container>
</my-custom-table>

【问题讨论】:

  • 我没有看到问题,但我也看不到“onLockChange”的定义位置,问题可能存在,因为这可能是 POST 调用和潜在切换的原因
  • 复制/粘贴时误漏了该行,已添加
  • 不幸的是,这实际上只是将问题推回了一层,我不确定“itemChangeSubject”是做什么的,而且我看不到您在哪里设置 item.toggled,所以我可以不评论可能出现的问题。我建议您从一组非常基本的代码开始(就像我在答案中包含的那样),然后逐步构建其余的组件功能,以确保您不会弄乱切换
  • 抱歉,它只是一个 ReplaySubject,其中包含单击切换的项目(只是表中的一行)。 private lockChangeSubject: ReplaySubject&lt;{ item: MyItem; }&gt; = new ReplaySubject(); 我认为我不需要显式设置 item.toggled,因为我正在设置 this.items$。我最初的 GET API 调用 (getItemsAndCache()) 返回 $items,然后将其传递给我的表进行迭代,每个项目上的一个道具是 toggled。在我的 POST 失败时,我发现了错误和 lastItems$.pipe(first()),它应该发出原始的 observable
  • 然后在这里执行此操作this.items$ = concat(lastItems$.pipe(first()), updatedItems$) as Observable&lt;MyItem[]&gt;; 应该会更改 $items,然后相应地更新表和切换,因为我使用的是异步管道。

标签: angular angular-material


【解决方案1】:

此答案基于 angular.material.io 中的示例:https://material.angular.io/components/slide-toggle/examples

如果您将组件中的一个变量绑定到滑动开关的[(ngModel)] 属性,那么您只需将该变量的值更改回其先前的状态,这将相应地更新 UI。

在您的 HTML 模板中,您可以像这样设置滑动切换:

<mat-slide-toggle [(ngModel)]="checked" (change)="postChangeToServer()">
    Slide me!
</mat-slide-toggle>

然后像这样设置你的组件打字稿:

@Component({
  selector: 'slide-toggle-example',
  templateUrl: 'slide-toggle-example.html',
})
export class SlideToggleExample {
  checked = false;

  postChangeToServer(): {
    //Do your POST call here and handle the negative response with the line below
    //For the sake of demonstration I've just set a one second timeout instead of making a server call

    setTimeout(() => {
      this.checked = !this.checked;
    }, 1000);
  }
}

【讨论】:

  • 嗯,这就是我正在做的,但我没有看到正确的行为。我将不得不深入研究我的代码,以确保我走在正确的轨道上
  • 如果您发布了一些代码,我或许可以帮助您追踪问题
  • 谢谢,我已经更新了我的问题以包含代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多