Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow hiding of selectAll checkbox & fix initial selection of disabled table rows #479

Merged
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import { BreadcrumbModule } from 'primeng/breadcrumb'
import { SkeletonModule } from 'primeng/skeleton'
import { MessageModule } from 'primeng/message'
import { SharedModule } from 'primeng/api'
import { CheckboxModule } from 'primeng/checkbox'

@NgModule({
imports: [
BreadcrumbModule,
CheckboxModule,
DropdownModule,
ButtonModule,
DialogModule,
Expand All @@ -33,6 +35,7 @@ import { SharedModule } from 'primeng/api'
],
exports: [
BreadcrumbModule,
CheckboxModule,
DropdownModule,
ButtonModule,
DialogModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
<ng-template pTemplate="header">
<tr>
<th style="width: 4rem" scope="col" *ngIf="selectionChangedObserved">
<p-tableHeaderCheckbox></p-tableHeaderCheckbox>
<p-tableHeaderCheckbox *ngIf="allowSelectAll"></p-tableHeaderCheckbox>
</th>
<ng-container *ngIf="actionColumnPosition === 'left';">
<ng-container *ngTemplateOutlet="actionColumnHeader"></ng-container>
Expand Down Expand Up @@ -194,10 +194,18 @@
<ng-template pTemplate="body" let-rowObject>
<tr>
<td *ngIf="selectionChangedObserved">
<p-tableCheckbox
[value]="rowObject"
[disabled]="!!selectionEnabledField && !fieldIsTruthy(rowObject, selectionEnabledField)"
></p-tableCheckbox>
<p-checkbox
*ngIf="(!!selectionEnabledField && !fieldIsTruthy(rowObject, selectionEnabledField)) && isSelected(rowObject); else defaultCheckbox"
[(ngModel)]="checked"
[binary]="true"
[disabled]="true"
></p-checkbox>
<ng-template #defaultCheckbox>
<p-tableCheckbox
[value]="rowObject"
[disabled]="!!selectionEnabledField && !fieldIsTruthy(rowObject, selectionEnabledField)"
></p-tableCheckbox>
</ng-template>
</td>
<ng-container *ngIf="actionColumnPosition === 'left';">
<ng-container *ngTemplateOutlet="actionColumn; context: {localRowObject: rowObject}"></ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { HAS_PERMISSION_CHECKER, IfPermissionDirective } from '../../directives/
import { ColumnType } from '../../model/column-type.model'
import { MenuModule } from 'primeng/menu'
import { DynamicLocaleId } from '../../utils/dynamic-locale-id'
import { CheckboxModule } from 'primeng/checkbox'
import { FormsModule } from '@angular/forms'

type DataTableInputTypes = Pick<DataTableComponent, 'rows' | 'columns' | 'emptyResultsMessage' | 'selectedRows'>

Expand All @@ -36,7 +38,7 @@ const DataTableComponentSBConfig: Meta<DataTableComponent> = {
}),
moduleMetadata({
declarations: [DataTableComponent, IfPermissionDirective],
imports: [TableModule, ButtonModule, MultiSelectModule, StorybookTranslateModule, MockAuthModule, MenuModule],
imports: [TableModule, ButtonModule, MultiSelectModule, StorybookTranslateModule, MockAuthModule, MenuModule, CheckboxModule, FormsModule],
}),
],
}
Expand All @@ -52,6 +54,7 @@ const dataTableActionsArgTypes = {

const dataTableSelectionArgTypes = {
selectionChanged: { action: 'selectionChanged' },
componentStateChanged: { action: 'componentStateChanged' },
}

const defaultComponentArgs: DataTableInputTypes = {
Expand Down Expand Up @@ -142,6 +145,16 @@ export const WithRowSelectionAndDefaultSelection = {
},
}

export const WithRowSelectionAndDisabledDefaultSelection = {
argTypes: dataTableSelectionArgTypes,
render: Template,
args: {
...defaultComponentArgs,
selectedRows: [1],
selectionEnabledField: 'available'
},
}

const extendedComponentArgs: DataTableInputTypes = {
columns: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,17 @@ import { isValidDate } from '@onecx/accelerator'
import { UserService } from '@onecx/angular-integration-interface'
import { MenuItem, PrimeTemplate, SelectItem } from 'primeng/api'
import { Menu } from 'primeng/menu'
import { BehaviorSubject, Observable, combineLatest, debounceTime, first, map, mergeMap, of } from 'rxjs'
import {
BehaviorSubject,
Observable,
combineLatest,
debounceTime,
first,
map,
mergeMap,
of,
withLatestFrom,
} from 'rxjs'
import { ColumnType } from '../../model/column-type.model'
import { DataAction } from '../../model/data-action'
import { DataSortDirection } from '../../model/data-sort-direction'
Expand Down Expand Up @@ -64,7 +74,7 @@ export interface DataTableComponentState {
})
export class DataTableComponent extends DataSortBase implements OnInit, AfterContentInit {
TemplateType = TemplateType

checked = true
_rows$ = new BehaviorSubject<Row[]>([])
@Input()
get rows(): Row[] {
Expand All @@ -74,14 +84,19 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
!this._rows$.getValue().length ?? this.resetPage()
this._rows$.next(value)
}
_selection$ = new BehaviorSubject<Row[]>([])
_selectionIds$ = new BehaviorSubject<(string | number)[]>([])
@Input()
get selectedRows(): Row[] {
return this._selection$.getValue()
}
set selectedRows(value: Row[]) {
this._selection$.next(value)
set selectedRows(value: Row[] | string[] | number[]) {
this._selectionIds$.next(
value.map((row) => {
if (typeof row === 'object') {
return row.id
}
return row
})
)
}

_filters$ = new BehaviorSubject<Filter[]>([])
@Input()
get filters(): Filter[] {
Expand Down Expand Up @@ -109,15 +124,15 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
}
columnTemplates$: Observable<Record<string, TemplateRef<any> | null>> | undefined
_columns$ = new BehaviorSubject<DataTableColumn[]>([])
@Input()
@Input()
get columns(): DataTableColumn[] {
return this._columns$.getValue()
}
set columns(value: DataTableColumn[]) {
this._columns$.next(value)
const obs = value.map((c) => this.getTemplate(c, TemplateType.CELL))
this.columnTemplates$ = combineLatest(obs).pipe(
map(values => Object.fromEntries(value.map((c, i) => [c.id, values[i]])))
map((values) => Object.fromEntries(value.map((c, i) => [c.id, values[i]])))
)
}
@Input() clientSideFiltering = true
Expand Down Expand Up @@ -155,6 +170,7 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
@Input() editActionVisibleField: string | undefined
@Input() editActionEnabledField: string | undefined
@Input() selectionEnabledField: string | undefined
@Input() allowSelectAll = true
@Input() paginator = true
@Input() page = 0
@Input()
Expand Down Expand Up @@ -187,13 +203,13 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
return this.numberCellTemplate || this.numberCellChildTemplate
}

/**
/**
* @deprecated Will be removed and instead to change the template of a specific column
* use the new approach instead by following the naming convention column id + IdCell
* e.g. for a column with the id 'status' use pTemplate="statusIdCell"
*/
@Input() customCellTemplate: TemplateRef<any> | undefined
/**
/**
* @deprecated Will be removed and instead to change the template of a specific column
* use the new approach instead by following the naming convention column id + IdCell
* e.g. for a column with the id 'status' use pTemplate="statusIdCell"
Expand Down Expand Up @@ -448,20 +464,21 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
}

emitComponentStateChanged(state: DataTableComponentState = {}) {
combineLatest([this.displayedPageSize$, this._selection$]).pipe(first()).subscribe(([pageSize, selectedRows]) => {
this.componentStateChanged.emit({
filters: this.filters,
sorting: {
sortColumn: this.sortColumn,
sortDirection: this.sortDirection
},
pageSize,
activePage: this.page,
selectedRows,
...state
})
})

this.displayedPageSize$
.pipe(withLatestFrom(this._selectionIds$, this._rows$), first())
.subscribe(([pageSize, selectedIds, rows]) => {
this.componentStateChanged.emit({
filters: this.filters,
sorting: {
sortColumn: this.sortColumn,
sortDirection: this.sortDirection,
},
pageSize,
activePage: this.page,
selectedRows: rows.filter((row) => selectedIds.includes(row.id)),
...state,
})
})
}

ngAfterContentInit() {
Expand Down Expand Up @@ -523,8 +540,8 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
this.emitComponentStateChanged({
sorting: {
sortColumn: sortColumn,
sortDirection: newSortDirection
}
sortDirection: newSortDirection,
},
})
}

Expand Down Expand Up @@ -564,7 +581,7 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
}
this.filtered.emit(filters)
this.emitComponentStateChanged({
filters
filters,
})
this.resetPage()
}
Expand Down Expand Up @@ -593,21 +610,55 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
}

mapSelectionToRows() {
this.selectedRows$ = combineLatest([this._selection$, this._rows$]).pipe(
map(([selectedRows, rows]) => {
return selectedRows.map((row) => {
return rows.find((r) => r.id === row.id)
this.selectedRows$ = combineLatest([this._selectionIds$, this._rows$]).pipe(
map(([selectedRowIds, rows]) => {
return selectedRowIds.map((rowId) => {
return rows.find((r) => r.id === rowId)
})
})
)
}

onSelectionChange(event: Row[]) {
this.selectedRows = event;
this.selectionChanged.emit(event)
this.emitComponentStateChanged({
selectedRows: event
onSelectionChange(selection: Row[]) {
let newSelectionIds = selection.map((row) => row.id)
const rows = this._rows$.getValue()

if (this.selectionEnabledField) {
const disabledRowIds = rows.filter((r) => !this.fieldIsTruthy(r, this.selectionEnabledField)).map((row) => row.id)
if (disabledRowIds.length > 0) {
newSelectionIds = this.mergeWithDisabledKeys(newSelectionIds, disabledRowIds)
}
}

this._selectionIds$.next(newSelectionIds)
this.selectionChanged.emit(this._rows$.getValue().filter((row) => newSelectionIds.includes(row.id)))
this.emitComponentStateChanged()
}

mergeWithDisabledKeys(newSelectionIds: (string | number)[], disabledRowIds: (string | number)[]) {
const previousSelectionIds = this._selectionIds$.getValue()
const previouslySelectedAndDisabled = previousSelectionIds.filter((id) => disabledRowIds.includes(id))
const disabledAndPreviouslyDeselected = disabledRowIds.filter((id) => !previousSelectionIds.includes(id))
const updatedSelection = [...newSelectionIds]

previouslySelectedAndDisabled.forEach((id) => {
if (!updatedSelection.includes(id)) {
updatedSelection.push(id)
}
})

disabledAndPreviouslyDeselected.forEach((id) => {
const index = updatedSelection.indexOf(id)
if (index > -1) {
updatedSelection.splice(index, 1)
}
})

return updatedSelection
}

isSelected(row: Row) {
return this._selectionIds$.getValue().includes(row.id)
}

onPageChange(event: any) {
Expand All @@ -618,7 +669,7 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
this.pageSizeChanged.emit(event.rows)
this.emitComponentStateChanged({
activePage: page,
pageSize: event.rows
pageSize: event.rows,
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@
[currentPageShowingKey]="currentPageShowingKey"
[currentPageShowingWithTotalOnServerKey]="currentPageShowingWithTotalOnServerKey"
[parentTemplates]="templatesForChildren$ | async"
[allowSelectAll]="tableAllowSelectAll"
[selectionEnabledField]="tableSelectionEnabledField"
>
</ocx-data-table>
<ng-template #stringCell let-rowObject="rowObject" let-column="column">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export class DataViewComponent implements DoCheck, OnInit, AfterContentInit {
@Input() viewActionEnabledField: string | undefined
@Input() editActionVisibleField: string | undefined
@Input() editActionEnabledField: string | undefined
@Input() tableSelectionEnabledField: string | undefined
@Input() tableAllowSelectAll = true
@Input() data: RowListGridData[] = []
@Input() name = 'Data table'
@Input() titleLineId: string | undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@
[currentPageShowingWithTotalOnServerKey]="currentPageShowingWithTotalOnServerKey"
(componentStateChanged)="dataViewComponentState$.next($event)"
[parentTemplates]="templates$ | async"
[tableAllowSelectAll]="tableAllowSelectAll"
[tableSelectionEnabledField]="tableSelectionEnabledField"
>
</ocx-data-view>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export class InteractiveDataViewComponent implements OnInit, AfterContentInit {
@Input() viewActionEnabledField: string | undefined
@Input() editActionVisibleField: string | undefined
@Input() editActionEnabledField: string | undefined
@Input() tableSelectionEnabledField: string | undefined
@Input() tableAllowSelectAll = true
@Input() name = 'Data'
@Input() titleLineId: string | undefined
@Input() subtitleLineIds: string[] = []
Expand Down
Loading