【问题标题】:Passing Selection Model Table Row To Server in Angular 7在Angular 7中将选择模型表行传递给服务器
【发布时间】:2020-02-07 06:52:49
【问题描述】:

我正在尝试将我通过复选框选择的表格行中的选定数据发送到服务器,但对如何通过服务发送数据有疑问。我有基本的骨架,但需要帮助来获取删除 REST API 调用的项目。使用 C# .Net Core JSON 调用作为此服务调用的服务器端点。

view.component.ts

    @Component({
  templateUrl: 'view.component.html'
})
export class ViewComponent implements OnInit, OnDestroy {

  // User Fields
  currentUser: User;
  users: User[] = [];
  currentUserSubscription: Subscription;

  loading : boolean;
  // Action Fields
  viewData: any;
  viewName: string;
  refNumber: number;
  currentActionSubscription: Subscription;
  displayedColumns: string[] = [];
  dataSource: any = new MatTableDataSource([]);
  pageSizeOptions: number[] = [10, 20, 50];

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

  selection = new SelectionModel<TableRow>(true, []);

  defaultSort: MatSortable = {
    id: 'defColumnName',
    start: 'asc',
    disableClear: true
  };

  defaultPaginator: MatPaginator;

  constructor(
    private iconRegistry: MatIconRegistry,
    private sanitizer: DomSanitizer,
    private actionService: ActionService
  ) {
    this.loading = false;
    this.iconRegistry.addSvgIcon(
      'thumbs-up',
      this.sanitizer.bypassSecurityTrustResourceUrl(
        'assets/img/examples/thumbup-icon.svg'
      )
    );
  }

  loadAction(action: any) {

    this.loading = true;
    // If there is already data loaded into the View, cache it in the service.
    if (this.viewData) {
      this.cacheAction();
    }

    if (this.sort) {
      // If there is sorting cached, load it into the View.
      if (action.sortable) {
        // If the action was cached, we should hit this block.
        this.sort.sort(action.sortable);
      } else {
        // Else apply the defaultSort.
        this.sort.sort(this.defaultSort);
      }
    }

    if (this.paginator) {
      // If we've stored a pageIndex and/or pageSize, retrieve accordingly.
      if (action.pageIndex) {
        this.paginator.pageIndex = action.pageIndex;
      } else { // Apply default pageIndex.
        this.paginator.pageIndex = 0;
      }

      if (action.pageSize) {
        this.paginator.pageSize = action.pageSize;
      } else { // Apply default pageSize.
        this.paginator.pageSize = 10;
      }
    }

    // Apply the sort & paginator to the View data.
    setTimeout(() => this.dataSource.sort = this.sort, 4000);
    setTimeout(() => this.dataSource.paginator = this.paginator, 4000);

    // Load the new action's data into the View:
    this.viewData = action.action;
    this.viewName = action.action.ActionName;
    this.refNumber = action.refNumber;

    // TODO: add uniquifiers/ids and use these as the sort for table

    const displayedColumns = this.viewData.Columns.map((c: { Name: any; }) => c.Name);
    displayedColumns[2] = 'Folder1';
    this.displayedColumns = ['select'].concat(displayedColumns);
    // tslint:disable-next-line: max-line-length
    const fetchedData = this.viewData.DataRows.map((r: { slice: (arg0: number, arg1: number) => { forEach: (arg0: (d: any, i: string | number) => any) => void; }; }) => {
      const row = {};
      r.slice(0, 9).forEach((d: any, i: string | number) => (row[this.displayedColumns[i]] = d));
      return row;
    });

    this.dataSource = new MatTableDataSource(fetchedData);
    this.loading = false;
  }

  // Stores the current Action, sort, and paginator in an ActionState object to be held in the action service's stateMap.
  cacheAction() {
    let actionState = new ActionState(this.viewData);

    // Determine the sort direction to store.
    let cachedStart: SortDirection;
    if (this.sort.direction == "desc") {
      cachedStart = 'desc';
    } else {
      cachedStart = 'asc';
    }

    // Create a Sortable so that we can re-apply this sort.
    actionState.sortable = {
      id: this.sort.active,
      start: cachedStart,
      disableClear: this.sort.disableClear
    };

    // Store the current pageIndex and pageSize.
    actionState.pageIndex = this.paginator.pageIndex;
    actionState.pageSize = this.paginator.pageSize;

    // Store the refNumber in the actionState for later retrieval.
    actionState.refNumber = this.refNumber;
    this.actionService.cacheAction(actionState);
  }

  ngOnInit() {
    // Subscribes to the action service's currentAction, populating this component with View data.
    this.actionService.currentAction.subscribe(action => this.loadAction(action));
  }

    /** Whether the number of selected elements matches the total number of rows. */
    isAllSelected() {
      const numSelected = this.selection.selected.length;
      const numRows = this.dataSource.data.length;
      return numSelected === numRows;
    }

    /** Selects all rows if they are not all selected; otherwise clear selection. */
    masterToggle() {
      this.isAllSelected()
        ? this.selection.clear()
        : this.dataSource.data.forEach((row: TableRow) => this.selection.select(row));
    }

    // Delete row functionality

    deleteRow() {
      console.log(this.selection);
      this.selection.selected.forEach(item => {
        const index: number = this.dataSource.data.findIndex((d: TableRow) => d === item);
        console.log(this.dataSource.data.findIndex((d: TableRow) => d === item));
        this.dataSource.data.splice(index, 1);
        this.dataSource = new MatTableDataSource<Element>(this.dataSource.data);
      });
      this.selection = new SelectionModel<TableRow>(true, []);
      this.actionService.deleteRow(this.selection).subscribe((response) => {
        console.log('Success!');
      });
    }


  ngOnDestroy() {

  }
}

view.service.ts

  deleteRow(selection: any): Observable<{}> {
console.log('testing service');
return this.http.delete<any>(`http://localhost:15217/actions/deleteRow`);

}

【问题讨论】:

  • 单删还是多删?
  • 根据集合中的对象单次或多次删除

标签: javascript angular typescript observable angular7


【解决方案1】:

您的代码目前需要做两件事:

  1. 以某种方式将所选行的 ID 传回服务器(通常通过 DELETE 请求中的 url)
  2. 订阅 observable 以实现它。目前 http 请求不会运行,因为它是一个没有任何订阅者的 observable。至少,组件中对服务的调用应该如下所示:
this.actionService.deleteRow(this.selection).subscribe((response) => {
  console.log('Success!');
});

编辑:

对于数字 1,这取决于您的服务器方法是什么样的。如果它接受一个数字 id 数组,则 view.service.ts 看起来像:

deleteRow(selection: SelectionModel<TableRow>): Observable<{}> {
  console.log('testing service');
  // create an array of query params using the property that you use to identify a table row
  const queryParams = selection.selected.map(row => `id=${row.id}`);
  // add the query params to the url
  const url = `http://localhost:15217/actions/deleteRow?${queryParams.join('&')}`;
  return this.http.delete<any>(url);
}

我在这里猜测您如何将有关表行的信息传递到您的服务器。如果您仍在为此苦苦挣扎,则需要提供一些有关 DELETE 端点的信息。

编辑 2:

现在我们对物体的外观有了更多了解...

deleteRow(selection: SelectionModel<TableRow>): Observable<{}> {
  console.log('testing service');
  // create an array of query params using the property that you use to identify a table row
  const queryParams = [...selection._selection].map(row => `id=${row.id}`);
  // add the query params to the url
  const url = `http://localhost:15217/actions/deleteRow?${queryParams.join('&')}`;
  return this.http.delete<any>(url);
}

【讨论】:

  • 对对...但是我将如何做 1 并可能扩展 2?这几乎是我需要帮助的地方
  • 我已经更新了我的答案,以说明数字 1 的外观,具体取决于您的服务器配置。数字 2 不需要太多扩展即可使其工作,尽管您可能希望在其中向用户提供一些反馈。你如何做到这一点完全取决于你,并且超出了这个问题的范围。
  • 嗯,这有帮助。我觉得我已经接近答案了,但我在控制台中也遇到了selection.map is not a function 的错误,我假设这是基于查询参数或所选行的 id。
  • 我不知道选择的结构是什么,所以我猜测它是一个数组。 map() 是一个数组函数。你能告诉我选择的数据结构是什么,那么我将能够提供更多帮助。
  • 这里不需要选择any类型,因为我想你知道数据类型是什么。
猜你喜欢
  • 1970-01-01
  • 2019-12-03
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2019-10-03
  • 1970-01-01
  • 2014-08-11
  • 2017-05-25
相关资源
最近更新 更多