diff --git a/README.md b/README.md
index e3902c2..68748ad 100644
--- a/README.md
+++ b/README.md
@@ -9,31 +9,60 @@ See the [Ag-Grid docs](https://www.ag-grid.com/documentation/react/getting-start
## Blocks
-Block types for supported [Ag-Grid themes](https://www.ag-grid.com/documentation/javascript/themes-provided/) are available.
+Block types for supported [Ag-Grid themes](https://www.ag-grid.com/documentation/javascript/themes-provided/) are available for for `dispay` and `input` block categories.
### Block type Urls
The block types are hosted at:
-- `AgGridAlpine`: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridAlpine.json
-- `AgGridAlpineDark`: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridAlpineDark.json
-- `AgGridBalham`: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridBalham.json
-- `AgGridBalhamDark`: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridBalhamDark.json
-- `AgGridMaterial`: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridMaterial.json
+- `AgGridAlpine`: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridAlpine.json
+- `AgGridAlpineDark`: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridAlpineDark.json
+- `AgGridBalham`: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridBalham.json
+- `AgGridBalhamDark`: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridBalhamDark.json
+- `AgGridMaterial`: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridMaterial.json
+- `AgGridInputAlpine`: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridInputAlpine.json
+- `AgGridInputAlpineDark`: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridInputAlpineDark.json
+- `AgGridInputBalham`: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridInputBalham.json
+- `AgGridInputBalhamDark`: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridInputBalhamDark.json
+- `AgGridInputMaterial`: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridInputMaterial.json
### Events
+##### All Blocks
+
+- `onCellClick`: Trigger event when a cell is clicked and pass `row: object`, `cell: object` and `selected: object[]` row data to action `_event`.
- `onRowClick`: Trigger event when a row is clicked and pass `row: object` and `selected: object[]` row data to action `_event`.
-- `onCellClick`:Trigger event when a cell is clicked and pass `row: object`, `cell: object` and `selected: object[]` row data to action `_event`.
+- `onRowSelected`: Trigger event when a row is selected and pass `row: object` and `selected: object[]` row data to action `_event`.
+- `onSelectionChanged`: Triggered when the selected rows is changed and pass `selected: object[]` row data to action `_event`.
+
+##### Input Blocks
+
+- `onCellValueChanged`: Triggered when a cell value is changed on the grid. The following is passed to the action `_event`:
+ - `field: string`: The field name of the changed cell.
+ - `newRowData: object[]`: The table data with the change applied.
+ - `newValue: any`: The updated cell value.
+ - `oldValue: any`: The cell value before the update was made.
+ - `rowData: object`: The row data after the cell value has been changed.
+ - `rowIndex: number`: Array index of the row for the changed cell.
+- `onRowDragMove`: Triggered when a row is dragged to another position in the grid. The following is passed to the action `_event`:
+ - `fromData: object`: Row data of the row selection which to moved.
+ - `fromIndex: number`: Array index of the row selection which to moved.
+ - `newRowData: object[]`: The table data with the change applied.
+ - `toData: object`: Row data of the row to which the selection will be moved.
+ - `toIndex: number`: Array index of the row to which the selection will be moved.
+
+### Methods
+
+- `exportDataAsCsv`: When called, table data will be downloaded in csv format.
### AgGridAlpine Example
```yaml
name: my-app
-lowdefy: 3.10.1
+lowdefy: 3.11.4
types:
AgGridAlpine:
- url: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridAlpine.json
+ url: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridAlpine.json
pages:
- id: dashboard
type: PageHeaderMenu
@@ -69,10 +98,10 @@ pages:
```yaml
name: my-app
-lowdefy: 3.10.1
+lowdefy: 3.11.4
types:
AgGridAlpine:
- url: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridAlpine.json
+ url: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridAlpine.json
pages:
- id: dashboard
type: PageHeaderMenu
@@ -117,10 +146,10 @@ pages:
```yaml
name: my-app
-lowdefy: 3.10.1
+lowdefy: 3.11.4
types:
AgGridAlpine:
- url: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridAlpine.json
+ url: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridAlpine.json
pages:
- id: dashboard
type: PageHeaderMenu
@@ -180,10 +209,10 @@ pages:
```yaml
name: my-app
-lowdefy: 3.10.1
+lowdefy: 3.11.4
types:
AgGridAlpine:
- url: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridAlpine.json
+ url: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridAlpine.json
pages:
- id: dashboard
type: PageHeaderMenu
@@ -241,10 +270,10 @@ pages:
```yaml
name: my-app
-lowdefy: 3.10.1
+lowdefy: 3.11.4
types:
AgGridAlpine:
- url: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridAlpine.json
+ url: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridAlpine.json
pages:
- id: dashboard
type: PageHeaderMenu
@@ -324,10 +353,10 @@ pages:
```yaml
name: my-app
-lowdefy: 3.10.1
+lowdefy: 3.11.4
types:
AgGridAlpine:
- url: https://blocks-cdn.lowdefy.com/v3.10.1/blocks-aggrid/meta/AgGridAlpine.json
+ url: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridAlpine.json
pages:
- id: dashboard
type: PageHeaderMenu
@@ -385,6 +414,132 @@ pages:
_state: all_selected
```
+### AgGridAlpine editable cells Example
+
+```yaml
+name: my-app
+lowdefy: 3.11.4
+types:
+ AgGridAlpine:
+ url: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridAlpine.json
+pages:
+ - id: dashboard
+ type: PageHeaderMenu
+ blocks:
+ - id: Download
+ type: Button
+ events:
+ onClick:
+ - id: download
+ type: CallMethod
+ params:
+ blockId: table
+ method: exportDataAsCsv
+ - id: table
+ type: AgGridAlpine
+ properties:
+ rowData:
+ - a: zero
+ b: 000
+ c: AA
+ - a: one
+ b: 111
+ c: BB
+ - a: two
+ b: 222
+ c: CC
+ columnDefs:
+ - field: 'a'
+ - field: 'b'
+ - field: 'c'
+```
+
+### AgGridInputAlpine onRowDragMove Example
+
+```yaml
+name: my-app
+lowdefy: 3.11.4
+types:
+ AgGridInputAlpine:
+ url: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridInputAlpine.json
+pages:
+ - id: dashboard
+ type: PageHeaderMenu
+ events:
+ onInit:
+ - id: new
+ type: SetState
+ params:
+ table:
+ - a: zero
+ b: 000
+ c: AA
+ - a: one
+ b: 111
+ c: BB
+ - a: two
+ b: 222
+ c: CC
+ blocks:
+ - id: table
+ type: AgGridInputAlpine
+ properties:
+ columnDefs:
+ - field: 'a'
+ rowDrag: true
+ - field: 'b'
+ - field: 'c'
+ - field: 'd'
+ defaultColDef:
+ width: 170
+ sortable: true
+ filter: true
+```
+
+### AgGridInputAlpine editable cells Example
+
+```yaml
+name: my-app
+lowdefy: 3.11.4
+types:
+ AgGridInputAlpine:
+ url: https://blocks-cdn.lowdefy.com/v3.11.4/blocks-aggrid/meta/AgGridInputAlpine.json
+pages:
+ - id: dashboard
+ type: PageHeaderMenu
+ events:
+ onInit:
+ - id: new
+ type: SetState
+ params:
+ table:
+ - a: zero
+ b: 000
+ c: AA
+ - a: one
+ b: 111
+ c: BB
+ - a: two
+ b: 222
+ c: CC
+ blocks:
+ - id: table
+ type: AgGridInputAlpine
+ properties:
+ columnDefs:
+ - field: 'a'
+ - field: 'b'
+ - field: 'c'
+ cellEditor: 'agSelectCellEditor'
+ cellEditorParams:
+ values: ['AA', 'BB', 'CC', 'DD']
+ defaultColDef:
+ width: 170
+ sortable: true
+ filter: true
+ editable: true
+```
+
## Other Lowdefy Blocks Packages
- [@lowdefy/blocks-template](https://github.com/lowdefy/blocks-template): Lowdefy template for creating blocks.
diff --git a/demo/examples/AgGridInputAlpine.yaml b/demo/examples/AgGridInputAlpine.yaml
new file mode 100644
index 0000000..85ea3f7
--- /dev/null
+++ b/demo/examples/AgGridInputAlpine.yaml
@@ -0,0 +1,48 @@
+- id: default
+ type: AgGridInputAlpine
+- id: table-basic
+ type: AgGridInputAlpine
+ properties:
+ rowData:
+ - title: One
+ year: 2010
+ viewerReviews: 30
+ - title: Two
+ year: 2011
+ viewerReviews: 20
+ columnDefs:
+ - headerName: Title
+ field: title
+ width: 350
+ - headerName: Year
+ field: year
+ width: 100
+ - headerName: Viewer Reviews
+ field: viewerReviews
+ width: 160
+ type: numericColumn
+- id: table-defaultColDef
+ type: AgGridInputAlpine
+ properties:
+ rowData:
+ - title: One
+ year: 2010
+ viewerReviews: 30
+ - title: Two
+ year: 2011
+ viewerReviews: 20
+ defaultColDef:
+ sortable: true
+ resizable: true
+ filter: true
+ columnDefs:
+ - headerName: Title
+ field: title
+ width: 350
+ - headerName: Year
+ field: year
+ width: 100
+ - headerName: Viewer Reviews
+ field: viewerReviews
+ width: 160
+ type: numericColumn
diff --git a/demo/examples/AgGridInputAlpineDark.yaml b/demo/examples/AgGridInputAlpineDark.yaml
new file mode 100644
index 0000000..54e4d34
--- /dev/null
+++ b/demo/examples/AgGridInputAlpineDark.yaml
@@ -0,0 +1,48 @@
+- id: default
+ type: AgGridInputAlpineDark
+- id: table-basic
+ type: AgGridInputAlpineDark
+ properties:
+ rowData:
+ - title: One
+ year: 2010
+ viewerReviews: 30
+ - title: Two
+ year: 2011
+ viewerReviews: 20
+ columnDefs:
+ - headerName: Title
+ field: title
+ width: 350
+ - headerName: Year
+ field: year
+ width: 100
+ - headerName: Viewer Reviews
+ field: viewerReviews
+ width: 160
+ type: numericColumn
+- id: table-defaultColDef
+ type: AgGridInputAlpineDark
+ properties:
+ rowData:
+ - title: One
+ year: 2010
+ viewerReviews: 30
+ - title: Two
+ year: 2011
+ viewerReviews: 20
+ defaultColDef:
+ sortable: true
+ resizable: true
+ filter: true
+ columnDefs:
+ - headerName: Title
+ field: title
+ width: 350
+ - headerName: Year
+ field: year
+ width: 100
+ - headerName: Viewer Reviews
+ field: viewerReviews
+ width: 160
+ type: numericColumn
diff --git a/demo/examples/AgGridInputBalham.yaml b/demo/examples/AgGridInputBalham.yaml
new file mode 100644
index 0000000..f69395f
--- /dev/null
+++ b/demo/examples/AgGridInputBalham.yaml
@@ -0,0 +1,48 @@
+- id: default
+ type: AgGridInputBalham
+- id: table-basic
+ type: AgGridInputBalham
+ properties:
+ rowData:
+ - title: One
+ year: 2010
+ viewerReviews: 30
+ - title: Two
+ year: 2011
+ viewerReviews: 20
+ columnDefs:
+ - headerName: Title
+ field: title
+ width: 350
+ - headerName: Year
+ field: year
+ width: 100
+ - headerName: Viewer Reviews
+ field: viewerReviews
+ width: 160
+ type: numericColumn
+- id: table-defaultColDef
+ type: AgGridInputBalham
+ properties:
+ rowData:
+ - title: One
+ year: 2010
+ viewerReviews: 30
+ - title: Two
+ year: 2011
+ viewerReviews: 20
+ defaultColDef:
+ sortable: true
+ resizable: true
+ filter: true
+ columnDefs:
+ - headerName: Title
+ field: title
+ width: 350
+ - headerName: Year
+ field: year
+ width: 100
+ - headerName: Viewer Reviews
+ field: viewerReviews
+ width: 160
+ type: numericColumn
diff --git a/demo/examples/AgGridInputBalhamDark.yaml b/demo/examples/AgGridInputBalhamDark.yaml
new file mode 100644
index 0000000..e6dbdb2
--- /dev/null
+++ b/demo/examples/AgGridInputBalhamDark.yaml
@@ -0,0 +1,48 @@
+- id: default
+ type: AgGridInputBalhamDark
+- id: table-basic
+ type: AgGridInputBalhamDark
+ properties:
+ rowData:
+ - title: One
+ year: 2010
+ viewerReviews: 30
+ - title: Two
+ year: 2011
+ viewerReviews: 20
+ columnDefs:
+ - headerName: Title
+ field: title
+ width: 350
+ - headerName: Year
+ field: year
+ width: 100
+ - headerName: Viewer Reviews
+ field: viewerReviews
+ width: 160
+ type: numericColumn
+- id: table-defaultColDef
+ type: AgGridInputBalhamDark
+ properties:
+ rowData:
+ - title: One
+ year: 2010
+ viewerReviews: 30
+ - title: Two
+ year: 2011
+ viewerReviews: 20
+ defaultColDef:
+ sortable: true
+ resizable: true
+ filter: true
+ columnDefs:
+ - headerName: Title
+ field: title
+ width: 350
+ - headerName: Year
+ field: year
+ width: 100
+ - headerName: Viewer Reviews
+ field: viewerReviews
+ width: 160
+ type: numericColumn
diff --git a/demo/examples/AgGridInputMaterial.yaml b/demo/examples/AgGridInputMaterial.yaml
new file mode 100644
index 0000000..02d7d3e
--- /dev/null
+++ b/demo/examples/AgGridInputMaterial.yaml
@@ -0,0 +1,48 @@
+- id: default
+ type: AgGridInputMaterial
+- id: table-basic
+ type: AgGridInputMaterial
+ properties:
+ rowData:
+ - title: One
+ year: 2010
+ viewerReviews: 30
+ - title: Two
+ year: 2011
+ viewerReviews: 20
+ columnDefs:
+ - headerName: Title
+ field: title
+ width: 350
+ - headerName: Year
+ field: year
+ width: 100
+ - headerName: Viewer Reviews
+ field: viewerReviews
+ width: 160
+ type: numericColumn
+- id: table-defaultColDef
+ type: AgGridInputMaterial
+ properties:
+ rowData:
+ - title: One
+ year: 2010
+ viewerReviews: 30
+ - title: Two
+ year: 2011
+ viewerReviews: 20
+ defaultColDef:
+ sortable: true
+ resizable: true
+ filter: true
+ columnDefs:
+ - headerName: Title
+ field: title
+ width: 350
+ - headerName: Year
+ field: year
+ width: 100
+ - headerName: Viewer Reviews
+ field: viewerReviews
+ width: 160
+ type: numericColumn
diff --git a/package.json b/package.json
index 8d38569..cdb3175 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@lowdefy/blocks-aggrid",
- "version": "3.11.1",
+ "version": "3.11.4",
"license": "MIT",
"description": "Lowdefy blocks for AgGrid.",
"homepage": "https://lowdefy.com",
@@ -45,7 +45,7 @@
"@ag-grid-community/all-modules": "25.1.0",
"@ag-grid-community/core": "25.1.0",
"@ag-grid-community/react": "25.1.0",
- "@lowdefy/block-tools": "^3.11.3",
+ "@lowdefy/block-tools": "^3.11.4",
"react": "17.0.1",
"react-dom": "17.0.1"
},
@@ -54,7 +54,7 @@
"@babel/core": "7.12.16",
"@babel/preset-env": "7.12.16",
"@babel/preset-react": "7.12.13",
- "@lowdefy/helpers": "^3.11.3",
+ "@lowdefy/helpers": "^3.11.4",
"babel-jest": "26.6.3",
"babel-loader": "8.2.2",
"buffer": "6.0.3",
diff --git a/src/AgGrid.js b/src/AgGrid.js
index 350c55b..37a58f6 100644
--- a/src/AgGrid.js
+++ b/src/AgGrid.js
@@ -34,6 +34,9 @@ class AgGrid extends React.Component {
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
+ this.props.methods.registerMethod('exportDataAsCsv', (args) =>
+ this.gridApi.exportDataAsCsv(args)
+ );
}
onRowClick(event) {
diff --git a/src/AgGridInput.js b/src/AgGridInput.js
new file mode 100644
index 0000000..8e73e79
--- /dev/null
+++ b/src/AgGridInput.js
@@ -0,0 +1,156 @@
+/*
+ Copyright 2021 Lowdefy, Inc
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+import React from 'react';
+
+import { AgGridReact } from '@ag-grid-community/react';
+import { AllCommunityModules } from '@ag-grid-community/all-modules';
+import '@ag-grid-community/all-modules/dist/styles/ag-grid.css';
+
+class AgGridInput extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.onGridReady = this.onGridReady.bind(this);
+ this.onRowClick = this.onRowClick.bind(this);
+ this.onCellClicked = this.onCellClicked.bind(this);
+ this.onRowSelected = this.onRowSelected.bind(this);
+ this.onSelectionChanged = this.onSelectionChanged.bind(this);
+ this.onRowDragMove = this.onRowDragMove.bind(this);
+ this.onCellValueChanged = this.onCellValueChanged.bind(this);
+ }
+
+ onGridReady(params) {
+ this.gridApi = params.api;
+ this.gridColumnApi = params.columnApi;
+ this.props.methods.registerMethod('exportDataAsCsv', (args) =>
+ this.gridApi.exportDataAsCsv(args)
+ );
+ }
+
+ onRowClick(event) {
+ if (this.props.events.onRowClick) {
+ this.props.methods.triggerEvent({
+ name: 'onRowClick',
+ event: { row: event.data, selected: this.gridApi.getSelectedRows() },
+ });
+ }
+ }
+
+ onCellClicked(event) {
+ if (this.props.events.onCellClick) {
+ this.props.methods.triggerEvent({
+ name: 'onCellClick',
+ event: {
+ row: event.data,
+ cell: { column: event.colDef.field, value: event.value },
+ selected: this.gridApi.getSelectedRows(),
+ },
+ });
+ }
+ }
+
+ onRowSelected(event) {
+ if (this.props.events.onRowSelected) {
+ this.props.methods.triggerEvent({
+ name: 'onRowSelected',
+ event: { row: event.data, selected: this.gridApi.getSelectedRows() },
+ });
+ }
+ }
+
+ onSelectionChanged() {
+ if (this.props.events.onSelectionChanged) {
+ this.props.methods.triggerEvent({
+ name: 'onSelectionChanged',
+ event: { selected: this.gridApi.getSelectedRows() },
+ });
+ }
+ }
+
+ onRowDragMove(event) {
+ if (event.overNode !== event.node) {
+ const fromData = event.node.data;
+ const toData = event.overNode.data;
+ const fromIndex = this.props.value.indexOf(fromData);
+ const toIndex = this.props.value.indexOf(toData);
+ const newRowData = this.props.value.slice();
+ const element = newRowData[fromIndex];
+ newRowData.splice(fromIndex, 1);
+ newRowData.splice(toIndex, 0, element);
+ this.props.methods.setValue(newRowData);
+ this.gridApi.setRowData(this.props.value);
+ this.gridApi.clearFocusedCell();
+ this.props.methods.triggerEvent({
+ name: 'onRowDragMove',
+ event: {
+ fromData,
+ toData,
+ fromIndex,
+ toIndex,
+ newRowData,
+ },
+ });
+ }
+ }
+
+ onCellValueChanged(params) {
+ const newRowData = this.props.value;
+ newRowData[params.rowIndex][params.colDef.field] = params.newValue;
+ this.props.methods.setValue(newRowData);
+ this.props.methods.triggerEvent({
+ name: 'onCellValueChanged',
+ event: {
+ rowIndex: params.rowIndex,
+ rowData: params.data,
+ field: params.colDef.field,
+ newValue: params.newValue,
+ oldValue: params.oldValue,
+ newRowData,
+ },
+ });
+ }
+
+ render() {
+ const {
+ rowSelection = 'single',
+ rowMultiSelectWithClick = this.props.properties.rowSelection === 'multiple',
+ quickFilterValue,
+ ...someProperties
+ } = this.props.properties;
+ if (quickFilterValue && quickFilterValue === '') {
+ this.gridApi.setQuickFilter(quickFilterValue); // check if empty string matches all
+ }
+ return (
+