Я использую ag-grid с Angular 8. Поскольку я использую его много раз в разных представлениях, я инкапсулировал компонент ag-grid в свою собственную реализацию компонента angular.
Теперь он предварительно настроен, и мне нужно передать только массив для данных таблицы и массив для выбора.
пример:
<myGrid
[rowData]="myTableData"
[(selection)]="mySelection"
(selectionChange)="onSelectionChange($event)"
>
</myGrid>
На основе выбранных строк на мой взгляд, кнопки включены или отключены. И это очень хорошо работает, когда я нажимаю прямо на строки в ag-сетке.
MyProblem
Когда я использую флажки и нажимаю напрямую на флажках кнопки не обновляются. Когда я нажимаю на строки, проблем нет, это когда нажимаю на флажки, где кнопки не обновляются.
Все остальное в порядке. Выбор производится в таблице, я даже могу записать выбранные строки, срабатывает событие onSelectionChange .. Просто кнопки не получают уведомления.
Мое объяснение
Вид не обновляется после того, как был сделан выбор. Либо событие, обновляющее представление, уже завершено до того, как сделан выбор, либо установка флажков не вызывает обнаружения изменений.
Мое решение
Использование ChangeDetectorRef#detectChanges()
.
-> Я устанавливаю флажок в своей сетке
-> (в MyGrid
компоненте) ag-grid запускает onSelectionChanged
функцию
-> событие для @Output
испускается вызовом this.selectionChange.emit(this.selection);
-> родительские компоненты реализуют функцию selectionChange($event)
и запускают this.changeDetectorRef.detectChanges()
Мой вопрос
ПОЧЕМУ? . Почему angular не обнаруживает изменения, когда я нажимаю на флажки, а только когда я нажимаю где-нибудь еще?
Дополнительные настройки более подробно:
В компоненте MyGrid
@Input('rowData') public rowData: any[] = []; // the array with the data for my table
@Input('selection') public selection: any[] = []; // the array that holds my selected rows
@Output() private selectionChange = new EventEmitter<any[]>(); // bi-directional so I can get and set the selection from within my parent component
EDIT
Я добавил сюда полные параметры. Как видите, они довольно просты, поэтому родительский компонент может инициализировать их по мере необходимости.
/ EDIT
this.agGridOptions = {
context: {thisComponent: this},
pagination: true,
paginationAutoPageSize: true,
rowDeselection: false,
rowSelection: this.rowSelectionMode, // parameterizable
suppressDragLeaveHidesColumns: true,
suppressMakeColumnVisibleAfterUnGroup: true,
groupUseEntireRow: true,
rowGroupPanelShow: 'always',
animateRows: true,
sideBar: this.sideBar, // parameterizable
defaultColDef: this.defaultColDef, // parameterizable
columnDefs: this.columnDefs, // parameterizable
getRowHeight: this.rowHeight, // parameterizable
onModelUpdated: () => this.sizeColumns(),
onSelectionChanged: () => this. onSelected(),
onGridReady: ($event) => this.onGridReady($event),
getContextMenuItems: ($event) => this.getContextMenuItems($event)
};
// and once the onSelectionChanged is triggered this function is called:
onSelected() {
this.selection = this.agGridApi.getSelectedRows(); // I update my bi-directional array for the selected rows
this.selectionChange.emit(this.selection); // and trigger the selectionChange event so the parent component knows that something happened
}
Теперь в моем родительском компоненте я должен реализовать это:
onSelectionChange($event: any[]) {
this.changeDetectorRef.detectChanges(); // otherwise angular won't update my buttons
}
EDIT
А вот как инициализируется массив с columnDefs
:
this.columnDefs.push(
// some factory function that creates something like this:
{
headerName : 'Some Column', // ex: "Employee"
field : 'fieldOfTheModelClass', // ex: employee.name
filter : 'agTextColumnFilter', // (for example)
checkboxSelection : true, // the checkbox causes the problem
valueGetter : null, // by default
cellClass : 'someCssClass'
cellRenderer : renderName() // a function to render the column value (if anything other than a string), maybe an image or icon
}
);