首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >角6分页器复制请求和响应

角6分页器复制请求和响应
EN

Stack Overflow用户
提问于 2018-10-03 21:42:52
回答 2查看 1.2K关注 0票数 0

我试图在一个带有分页器的mat表上创建一个搜索,当组件加载的功能与预期相同时,当我单击下一个页面并在开发人员工具中查看网络时,我会看到一个请求和一个响应,当我现在搜索它仍然发出一个请求和一个响应时,但是当我在下一页搜索时,我看到它发出了两个请求,得到了两个响应,所以它是重复的;如果我再次搜索,它在下一个页面之后发出3个请求和响应,等等,然后我再次单击下一个页面,但是每次搜索仍然只有一个请求和响应。

想知道是否有人能在这个问题上引导我做正确的事。

这是我的组件

代码语言:javascript
复制
    import {Component, OnInit, ViewChild} from '@angular/core';
    import {MatDialogRef,MatDialog} from '@angular/material'
    import {MatPaginator, MatSort} from '@angular/material';
    import {merge, Observable, of as observableOf} from 'rxjs';
    import {catchError, map, startWith, switchMap} from 'rxjs/operators';
    import {DataService} from '@app/providers'
    import {UserAdd} from '@app/modules/features/admininstration/pages/users/modals/user_add/user_add'
    import {UserEdit} from '@app/modules/features/admininstration/pages/users/modals/user_edit/user_edit'
    import {UserOtp} from '@app/modules/features/admininstration/pages/users/modals/user_otp/user_otp'
    import * as u from '@app/models/user'

    /**
     * @title Table retrieving data through HTTP
     */
    @Component({
      selector: 'users',
      styleUrls: ['users.scss'],
      templateUrl: 'users.html',
    })
    export class Users implements OnInit {
      displayedColumns: string[] = ['username', 'firstname', 'surname','userrole','usertype', 'created','actions'];
      data: u.UserGrid[] = []
      search: string = "";
      resultsLength = 0;
      isLoadingResults = true;
      isRateLimitReached = false;

      userAdd: MatDialogRef<UserAdd>;
      userEdit: MatDialogRef<UserEdit>;
      userOtp: MatDialogRef<UserOtp>;

      @ViewChild(MatPaginator) paginator: MatPaginator;
      @ViewChild(MatSort) sort: MatSort;

      constructor(private ds:DataService,private dialog:MatDialog) {}

      ngOnInit() {
        // If the user changes the sort order, reset back to the first page.
        this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);
        this.sort.direction = 'asc';
        this.sort.active = 'firstname';
        this.loadGridData();
      }

      loadGridData(){

        merge(this.sort.sortChange, this.paginator.page)
          .pipe(
            startWith({}),
            switchMap(() => {
              this.isLoadingResults = true;
              return this.ds!.getUsers(this.search,this.sort.active+'_'+this.sort.direction,10,this.paginator.pageIndex);
            }),
            map(data => {
              // Flip flag to show that loading has finished.
              this.isLoadingResults = false;
              this.isRateLimitReached = false;
              this.resultsLength = data.count;
              return data.users;
            }),
            catchError(() => {
              this.isLoadingResults = false;
              this.isRateLimitReached = true;
              return observableOf([]);
            })
          ).subscribe(data => this.data = data); 
      }

      userSearch(){
        this.paginator.pageIndex = 0;
        this.loadGridData();
      }

      openUserAdd(){
        this.userAdd = this.dialog.open(UserAdd,{
          disableClose: false,
          width: '550px',
          height: '50%',
        })
      }

      openUserEdit(id:string){
        this.userEdit = this.dialog.open(UserEdit,{
          disableClose: false,
          width: '550px',
          height: '50%',
        })
        this.userEdit.componentInstance.id = id;
      }

      openUserOtp(){
        this.userOtp = this.dialog.open(UserOtp,{
          disableClose: false,
          width: '500px',
          height: '150px'
        })
      }

      deleteUser(id:string){
        this.ds.deleteUser(id).subscribe(()=>{
          this.loadGridData();
        });

      }
    }

这是我的模板。

代码语言:javascript
复制
    <mat-toolbar color="accent" class="mini-toolbar" fxLayout="row" fxLayoutAlign="space-between center">
        <span>Users</span>

        <div fxLayout="row">
            <mat-form-field class="full-width" fxLayoutAlign="center center">
                <input placeholder="What are you looking for?" matInput [(ngModel)]="search" (keyup.enter)="userSearch()">
            </mat-form-field>
            <div fxFlex="10px"></div>
            <div class="custom_button" style="margin-top: 13px; width: 100px" fxLayoutAlign="center center" (keyup.enter)="userSearch()"
                (click)="userSearch()">
                SEARCH
            </div>
            <div fxFlex="10px"></div>
            <div class="custom_button" style="margin-top: 13px;width: 150px" fxLayoutAlign="center center" (click)="openUserAdd()">
                CREATE USER
            </div>
        </div>
    </mat-toolbar>

    <div class="example-loading-shade" *ngIf="isLoadingResults || isRateLimitReached">
        <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
        <div class="example-rate-limit-reached" *ngIf="isRateLimitReached">
            Error retrieving data.
        </div>
    </div>

    <div fxLayout="row" class="sitegroup-container" fxLayoutAlign="start stretch">
        <div fxFlex="100%" class="data_container">


            <table mat-table [dataSource]="data" class="example-table" matSort matSortActive="firstname" matSortDisableClear matSortDirection="asc">
                <!-- Username Column -->
                <ng-container matColumnDef="username">
                    <th mat-header-cell *matHeaderCellDef>Username</th>
                    <td mat-cell *matCellDef="let row">{{row.username}}</td>
                </ng-container>

                <!-- Firstname Column -->
                <ng-container matColumnDef="firstname">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>Firstname</th>
                    <td mat-cell *matCellDef="let row">{{row.firstname}}</td>
                </ng-container>

                <!-- Surname Column -->
                <ng-container matColumnDef="surname">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>Surname</th>
                    <td mat-cell *matCellDef="let row">{{row.surname}}</td>
                </ng-container>

                <!-- UserROle Column -->
                <ng-container matColumnDef="userrole">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>User Role</th>
                    <td mat-cell *matCellDef="let row">{{row.userRole}}</td>
                </ng-container>

                <!-- UserType Column -->
                <ng-container matColumnDef="usertype">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>User Type</th>
                    <td mat-cell *matCellDef="let row">{{row.userType}}</td>
                </ng-container>

                <!-- Created Column -->
                <ng-container matColumnDef="created">
                    <th mat-header-cell *matHeaderCellDef>
                        Created
                    </th>
                    <td mat-cell *matCellDef="let row">{{row.created | date}}</td>
                </ng-container>

                <!-- Actions Column-->
                <ng-container matColumnDef="actions">
                    <th mat-header-cell *matHeaderCellDef>

                    </th>
                    <td mat-cell *matCellDef="let row">
                        <div fxLayout="row" fxLayoutAlign="end">
                            <button matTooltip="OTP" [matTooltipPosition]="'left'" mat-icon-button (click)="openUserOtp()" color="accent">
                                <mat-icon>smartphone</mat-icon>
                            </button>
                            <button matTooltip="Edit" [matTooltipPosition]="'left'" mat-icon-button (click)="openUserEdit(row.id)" color="accent">
                                <mat-icon>create</mat-icon>
                            </button>
                            <button matTooltip="Delete" [matTooltipPosition]="'left'" mat-icon-button (click)="deleteUser(row.id)" color="accent">
                                <mat-icon>delete</mat-icon>
                            </button>
                        </div>
                    </td>
                </ng-container>

                <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
                <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
            </table>
            <mat-paginator [length]="resultsLength" [pageSize]="10"></mat-paginator>
        </div>
    </div>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-17 11:44:09

我更改了我的userSearch函数,并添加了一个refreshGrid函数来获取用户和resultsLength,而不是调用loadGrid函数,这样我就不会继续添加更多的订阅。

代码语言:javascript
复制
userSearch(){
    this.paginator.pageIndex = 0;
    this.refreshGrid();
  }

refreshGrid(){
    this.isLoadingResults = true;
    this.ds!.getUsers(this.search,this.sort.active+'_'+this.sort.direction,10,this.paginator.pageIndex).subscribe((data)=>{
      this.resultsLength = data.count;
      this.data = data.users;
      this.isLoadingResults = false;
    })
}
票数 0
EN

Stack Overflow用户

发布于 2018-10-04 16:08:43

每次调用loadGridData()时,都会订阅在合并上可观察到的构建。在没有删除订阅的情况下,您在代码中执行了几次此操作。因此,添加或删除用户将创建一个全新的订阅,因为您再次调用loadGridData(),增加了您正在进行的http调用的数量(由于链上的更改,较旧的订阅将触发)。

您的数据加载方式有几个基本问题,我建议您重新评估这一点。

一些建议:

  • 不要在后台代码中使用直接订阅,而是将“加载”的结果放入可观察的属性中,使用“异步”在模板上绑定该属性。
  • 将执行http请求的代码移动到主题中,并使合并中的混合内容可观察到。现在,您可以让subject发出更新的值,您的UI应该更新,而不是调用整个加载。

如果您使用异步,则角框架负责订阅外部可观测对象(来自主题的订阅)。

注-用下面的示例替换这里的一些评论

下面是一个简单的示例,希望这将显示一种方法来避免不断添加的调用。

app.component.html

代码语言:javascript
复制
<div>
  <button (click)="loadData()">Refresh</button>
</div>
<div *ngIf="currentTime$ | async as currentTime">
  <p>{{currentTime.currentFileTime}}</p>
</div>

app.component.ts

代码语言:javascript
复制
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map, take } from 'rxjs/operators';
import { Subject } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  public currentTime$ = new Subject<any>();
  private httpClient: HttpClient;

  constructor(http: HttpClient) {
    this.httpClient = http;
  }

  public ngOnInit() {
    this.loadData();
  }

  public loadData() {
    const path = 'http://worldclockapi.com/api/json/est/now';

    const subscription = this.httpClient.get<any>(path).pipe(take(1), map((val) => val)).subscribe(
      (data) => {
        this.currentTime$.next(data);
      },
      (error) => {
        console.log(error);
      },
      () => {
        if (subscription && !subscription.closed) {
          subscription.unsubscribe();
        }
      });
  }
}

app.module.ts

代码语言:javascript
复制
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [ ],
  bootstrap: [AppComponent]
})
export class AppModule { }

因此,每当您按"Refresh“时,都会生成一个http调用,但是旧的订阅会在完成时关闭。“采取(1)”导致完成在第一次获得,从而使这种行为方式,我认为您希望您的数据流。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52636091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档