Skip to content

Commit

Permalink
fix(selection): 修改 review 建议 #WIK-16060
Browse files Browse the repository at this point in the history
  • Loading branch information
cmm-va committed Jul 22, 2024
1 parent 0f12102 commit aef4cc8
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 206 deletions.
17 changes: 5 additions & 12 deletions packages/grid/src/grid.component.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div class="grid-header d-flex">
<div class="grid-column-checkbox grid-cell">
<label thyCheckbox thyLabelText="" [(ngModel)]="isSelectedAll" (ngModelChange)="toggleSelectAll()"></label>
<label thyCheckbox thyLabelText="" [ngModel]="isSelectedAll" (ngModelChange)="toggleSelectAll($event)"></label>
</div>
@for (field of gridData().fields; track field.id) {
<div class="grid-cell grid-column-field" #fieldAction (click)="selectCol(field)" [attr.fieldId]="field.id">
<div class="grid-cell grid-column-field" #fieldAction [attr.fieldId]="field.id">
{{ field.name }}
<a thyAction thyActiveClass="active" thyIcon="more-vertical" [thyDropdown]="fieldMenu" href="javascript:;">
<thy-dropdown-menu #fieldMenu>
Expand All @@ -24,20 +24,13 @@
[ngClass]="record.checked ? 'checked-box' : 'unchecked-box'"
thyCheckbox
thyLabelText=""
[(ngModel)]="record.checked"
(ngModelChange)="selectRow(record)"
[ngModel]="record.checked"
(ngModelChange)="selectRow(record.id)"
></label>
<span [ngClass]="record.checked ? 'grid-row-no-number' : 'grid-row-number'"> {{ index + 1 }} </span>
</div>
@for (field of gridData().fields; track $index) {
<div
class="grid-cell"
[attr.type]="[field.type]"
[attr.fieldId]="[field.id]"
[attr.recordId]="[record.id]"
#cell
(click)="selectCell(record.id, field.id)"
>
<div class="grid-cell" [attr.type]="[field.type]" [attr.fieldId]="[field.id]" [attr.recordId]="[record.id]" #cell>
@switch (field.type) {
@case (AITableFieldType.SingleSelect) {
@if (record.value[field.id] | selectOption: field['options']; as selectedOption) {
Expand Down
83 changes: 18 additions & 65 deletions packages/grid/src/grid.component.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
import {
ChangeDetectionStrategy,
Component,
computed,
effect,
ElementRef,
input,
model,
OnInit,
output,
signal,
viewChild
} from '@angular/core';
import { ChangeDetectionStrategy, Component, computed, ElementRef, input, model, OnInit, output, signal, viewChild } from '@angular/core';
import { CommonModule, NgClass, NgComponentOutlet, NgForOf } from '@angular/common';
import { SelectedOneFieldPipe, SelectOptionPipe } from './pipes/grid';
import { SelectOptionPipe } from './pipes/grid';
import { ThyTag } from 'ngx-tethys/tag';
import { ThyPopover, ThyPopoverModule } from 'ngx-tethys/popover';
import { ThyPopoverModule } from 'ngx-tethys/popover';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { buildGridData } from './utils';
import { AIFieldConfig, AITableFieldMenu, AITableRowHeight } from './types';
import { AIFieldConfig, AITableFieldMenu, AITableRowHeight, AITableSelection } from './types';
import {
Actions,
createAITable,
Expand All @@ -27,8 +15,6 @@ import {
AITableFields,
AITableFieldType,
AITableRecords,
AITableField,
AITableRecord,
createDefaultField
} from './core';
import { ThyIcon } from 'ngx-tethys/icon';
Expand Down Expand Up @@ -97,10 +83,8 @@ export class AITableGrid implements OnInit {

aiTable!: AITable;

isSelectedAll = false;

get selection() {
return this.aiTableGridSelectionService.selection();
get isSelectedAll() {
return this.aiTable.selection().selectedRecords.size === this.aiRecords().length;
}

onChange = output<AITableChangeOptions>();
Expand All @@ -110,29 +94,25 @@ export class AITableGrid implements OnInit {
fieldMenus!: AITableFieldMenu[];

gridData = computed(() => {
return buildGridData(this.aiRecords(), this.aiFields());
return buildGridData(this.aiRecords(), this.aiFields(), this.aiTable.selection());
});

constructor(
private elementRef: ElementRef,
private aiTableGridEventService: AITableGridEventService,
private thyPopover: ThyPopover,
public aiTableGridSelectionService: AITableGridSelectionService,
private aiTableGridFieldService: AITableGridFieldService
) {
effect(
() => {
this.aiTable.selection.set(this.aiTableGridSelectionService.selection());
console.log('跟新啦', this.aiTable.selection());
},
{ allowSignalWrites: true }
);
}
) {}

ngOnInit(): void {
this.initAITable();
this.initService();
this.buildFieldMenus();
this.aiTableGridEventService.mousedownEvent$.subscribe((event) => {
if (event?.target) {
this.aiTableGridSelectionService.updateSelect(event);
}
});
}

initAITable() {
Expand All @@ -149,6 +129,7 @@ export class AITableGrid implements OnInit {

initService() {
this.aiTableGridEventService.initialize(this.aiTable, this.aiFieldConfig()?.fieldPropertyEditor);
this.aiTableGridSelectionService.initialize(this.aiTable);
this.aiTableGridEventService.registerEvents(this.elementRef.nativeElement);
this.aiTableGridFieldService.initAIFieldConfig(this.aiFieldConfig());
AI_TABLE_GRID_FIELD_SERVICE_MAP.set(this.aiTable, this.aiTableGridFieldService);
Expand All @@ -162,40 +143,12 @@ export class AITableGrid implements OnInit {
Actions.addRecord(this.aiTable, getDefaultRecord(this.aiFields()), [this.aiRecords().length]);
}

toggleAllCheckbox(checked: boolean) {
const data = this.gridData().records.map((item) => {
return { ...item, checked: checked };
});
this.gridData().records = data;
}

selectCell(recordId: string, fieldId: string) {
this.toggleAllCheckbox(false);
this.isSelectedAll = false;
this.aiTableGridSelectionService.selectCell(recordId, fieldId);
}

selectCol(field: any) {
this.toggleAllCheckbox(false);
this.isSelectedAll = false;
this.aiTableGridSelectionService.selectCol(field.id);
selectRow(recordId: string) {
this.aiTableGridSelectionService.selectRow(recordId);
}

selectRow(record: AITableRecord) {
this.aiTableGridSelectionService.selectRow(record.id);
this.isSelectedAll = this.selection.selectedRecords.size === this.aiRecords().length;
}

toggleSelectAll() {
this.aiTableGridSelectionService.clearSelection();
if (this.isSelectedAll) {
this.toggleAllCheckbox(true);
this.aiRecords().forEach((item) => {
this.selectRow(item);
});
} else {
this.toggleAllCheckbox(false);
}
toggleSelectAll(checked: boolean) {
this.aiTableGridSelectionService.toggleSelectAll(checked);
}

addField(gridColumnBlank: HTMLElement) {
Expand Down
117 changes: 5 additions & 112 deletions packages/grid/src/services/event.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Injectable, Renderer2, Signal } from '@angular/core';
import { Injectable, Renderer2, Signal, WritableSignal, signal } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { fromEvent } from 'rxjs';
import { fromEvent, Subject } from 'rxjs';
import { DBL_CLICK_EDIT_TYPE } from '../constants';
import { getRecordOrField } from '../utils';
import { AITable, AITableField, AITableFieldType, AITableRecord } from '../core';
Expand All @@ -16,12 +16,9 @@ export class AITableGridEventService {

takeUntilDestroyed = takeUntilDestroyed();

lastClickCellElement?: HTMLElement;
mousedownEvent$ = new Subject<MouseEvent>();

constructor(
private thyPopover: ThyPopover,
private renderer: Renderer2
) {}
constructor(private thyPopover: ThyPopover) {}

initialize(aiTable: AITable, aiFieldRenderers?: Partial<Record<AITableFieldType, AITableGridCellRenderSchema>>) {
this.aiTable = aiTable;
Expand All @@ -38,114 +35,10 @@ export class AITableGridEventService {
fromEvent<MouseEvent>(element, 'click')
.pipe(this.takeUntilDestroyed)
.subscribe((event) => {
this.click(event as MouseEvent);
this.mousedownEvent$.next(event as MouseEvent);
});
}

updateCellClass(dom: Element, operation: string) {
const rowDom = dom.closest('.grid-row');
const highlightCells = rowDom?.querySelectorAll('.grid-cell');
highlightCells?.forEach((cell) => {
operation === 'remove' ? this.renderer.removeClass(cell, 'highlight') : this.renderer.addClass(cell, 'highlight');
});
operation === 'remove' ? this.renderer.removeClass(dom, 'isSelected') : this.renderer.addClass(dom, 'isSelected');
}

updateColClass(dom: Element, operation: string) {
const fieldId = dom.getAttribute('fieldid');
const tableElement = dom.closest('ai-table-grid');
const cells = tableElement?.querySelectorAll(`[fieldid="${fieldId}"]`);
cells?.forEach((cell) => {
operation === 'add' ? this.renderer.addClass(cell, 'highlight') : this.renderer.removeClass(cell, 'highlight');
});
}

updateAllClass(dom: Element, operation: string, checked: boolean) {
const tableElement = dom.closest('ai-table-grid');
const rows = tableElement?.querySelectorAll('.grid-row');
if (checked && operation === 'add') {
rows?.forEach((row) => {
this.renderer.addClass(row, 'highlight');
});
}
if (operation === 'remove') {
rows?.forEach((row) => {
this.renderer.removeClass(row, 'highlight');
});
}
}

private click(event: MouseEvent) {
const cell = this.cellType(event.target as HTMLElement);
if (this.lastClickCellElement) {
const lastCell = this.cellType(this.lastClickCellElement);
if (lastCell?.type === 'cell') {
this.updateCellClass(this.lastClickCellElement, 'remove');
}

if (lastCell?.type === 'row' && cell?.type !== 'row' && cell.type) {
const tableElement = lastCell.element.closest('ai-table-grid');
const checkboxes = tableElement?.querySelectorAll('.checked-box');
checkboxes?.forEach((box) => {
const row = box.closest('.grid-row');
this.renderer.removeClass(row, 'highlight');
});
}

if (lastCell.type === 'col') {
this.updateColClass(lastCell.element, 'remove');
}

if (lastCell?.type === 'all' && cell?.type !== 'row' && cell.type) {
this.updateAllClass(cell.element, 'remove', false);
}
}

if (cell?.type === 'cell') {
this.updateCellClass(cell.element, 'add');
}

if (cell?.type === 'row') {
const rowDom = cell.element.closest('.grid-row');
if ((event.target as HTMLInputElement).checked) {
this.renderer.addClass(rowDom, 'highlight');
} else {
this.renderer.removeClass(rowDom, 'highlight');
}
}

if (cell?.type === 'col') {
this.updateColClass(cell.element, 'add');
}

if (cell?.type === 'all') {
this.updateAllClass(cell.element, 'add', (event.target as HTMLInputElement).checked);
}

this.lastClickCellElement = event.target as HTMLElement;
}

private cellType(cell: HTMLElement) {
const cellDom = cell.closest('.grid-cell');
const rowDom = cell.closest('.grid-row-index');
const colDom = cell.closest('.grid-column-field');
const checkAllDom = cell.closest('.grid-column-checkbox');
if (cellDom && cellDom.getAttribute('fieldid') && cellDom.getAttribute('recordid')) {
return { type: 'cell', element: cellDom };
}
if (rowDom && cell.tagName === 'INPUT') {
return { type: 'row', element: rowDom };
}
if (colDom) {
return { type: 'col', element: colDom };
}

if (checkAllDom && cell.tagName === 'INPUT') {
return { type: 'all', element: checkAllDom };
}
return {};
}

private dblClick(event: MouseEvent) {
const cellDom = (event.target as HTMLElement).closest('.grid-cell') as HTMLElement;
const type = cellDom && cellDom.getAttribute('type')!;
Expand Down
Loading

0 comments on commit aef4cc8

Please sign in to comment.