Skip to content

Commit

Permalink
fix(utils): kill command in UnRx
Browse files Browse the repository at this point in the history
fix(ngrid): filler should update when collection change
refactor(ngrid): add "onDestroy" table event
fix(ngrid): clear context when datasource change
fix(ngrid): update paginator when datasource change
fix(ngrid/detail-row): populate row in detail toggle event
feat(ngrid): bind / unbind table to datasource (external)
  • Loading branch information
shlomiassaf committed May 8, 2019
1 parent 6a41cd0 commit c06bc17
Show file tree
Hide file tree
Showing 26 changed files with 3,106 additions and 85 deletions.
1 change: 0 additions & 1 deletion README.md
Expand Up @@ -74,7 +74,6 @@ For example, column resize & reorder will all work programmatically without a pl
> Currently, `@pebula/ngrid-material` is the only rich UI layer, implementing the UI using `@angular/material`. You can also implemented your own, see how it's done in `@pebula/ngrid-material`.

## Design goals

- Developer ergonomics
Expand Down
5 changes: 4 additions & 1 deletion TODO.md
Expand Up @@ -8,14 +8,17 @@

- API reference document

- CI/CD integration
- CI/CD integration (including starter app integration on release)

- E2E tests using Cypress

- Add `@pebula/ngrid-bootstrap` based on https://ng-bootstrap.github.io?

- Add pre-built (compiled) css theme file to the release

- Support serialization of column definitions
- Support save / loan of table column defs

- `@pebula/ngrid-material`
- Complete cell **view** templates to all types
- Add cell **edit** templates to all types
Expand Down
Expand Up @@ -20,6 +20,13 @@
[disabled]="selectedDemoLink === demoLink"
[routerLink]="demoLink.cmd">{{ demoLink.text }}</a>
</mat-menu>
<div style="flex:1 0 auto"></div>
<a mat-button href="https://github.com/shlomiassaf/ngrid" target="_blank">
<svg style="fill: white" height="32" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true">
<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path>
</svg>
</a>

</nav>
</div>
<div class="main-view">
Expand Down
19 changes: 19 additions & 0 deletions lerna.json
@@ -0,0 +1,19 @@
{
"version": "independent",
"npmClient": "yarn",
"command": {
"publish": {
"ignoreChanges": ["ignored-file", "*.md"],
"conventionalCommits": true,
"message": "chore(release): release"
},
"version": {
"push": false
}
},
"packages": [
"libs/utils",
"libs/ngrid",
"libs/ngrid-material"
]
}
@@ -0,0 +1,3 @@
<docsi-bt-source-code-ref file="./filler.component.ts" [section]='["ex-1"]'></docsi-bt-source-code-ref>
<docsi-bt-source-code-ref file="./filler.component.md" lang="html" [section]='["ex-1"]'></docsi-bt-source-code-ref>
<docsi-bt-compile-markdown src="./filler.component.md"></docsi-bt-compile-markdown>
@@ -0,0 +1,38 @@
# Grid Filler

The table's background is transparent, when the total height of the rows is lower then the height available this is visible.

The filler is a `<div>` that is added at the bottom of the grid and takes up
the height left.

You can customize it's background through the CSS class `pbl-ngrid-space-fill`

I> You can also solve this by assigning a background color to the table but this is not always suitable.

In the following example the table is rendered inside a div container that has a `lightgreen` background color.

<docsi-mat-example-with-source title="Filler" contentClass="mat-elevation-z7" [query]="[{section: 'ex-1'}]">
<!--@pebula-example:ex-1-->
<div class="filler-table-container">
<pbl-ngrid blockUi vScrollAuto [dataSource]="dsVScrollAuto" [columns]="columns">
<pbl-demo-action-row filter ></pbl-demo-action-row>
</pbl-ngrid>
</div>
<!--@pebula-example:ex-1-->
</docsi-mat-example-with-source>

#### The same thing, now with fixed mode virtual scroll:

<div class="filler-table-container">
<pbl-ngrid blockUi vScrollFixed [dataSource]="dsVScrollFixed" [columns]="columns">
<pbl-demo-action-row filter " ></pbl-demo-action-row>
</pbl-ngrid>
</div>

W> Currently, the filler is not supported when virtual scroll is disabled (`vScrollNone`)

<div class="filler-table-container">
<pbl-ngrid blockUi vScrollNone [dataSource]="dsVScrollNone" [columns]="columns">
<pbl-demo-action-row filter " ></pbl-demo-action-row>
</pbl-ngrid>
</div>
@@ -0,0 +1,9 @@
.filler-table-container {
padding: 16px;
height: 400px;
background: lightgreen;

pbl-ngrid {
height: 100%;
}
}
@@ -0,0 +1,34 @@
/* @pebula-example:ex-1 */
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { createDS, columnFactory } from '@pebula/ngrid';

import { Person, DemoDataSource } from '@pebula/apps/ngrid/shared';

const COLUMNS = columnFactory()
.table(
{ prop: 'id', sort: true, width: '40px' },
{ prop: 'name', sort: true },
{ prop: 'gender', width: '50px' },
{ prop: 'birthdate', type: 'date' },
{ prop: 'email', minWidth: 250, width: '250px' },
{ prop: 'language', headerType: 'language' },
)
.build();

@Component({
selector: 'pbl-filler-grid-example-component',
templateUrl: './filler.component.html',
styleUrls: ['./filler.component.scss'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FillerGridExampleComponent {

columns = COLUMNS;
dsVScrollAuto = createDS<Person>().onTrigger( () => this.datasource.getPeople(0, 3) ).create();
dsVScrollFixed = createDS<Person>().onTrigger( () => this.datasource.getPeople(0, 3) ).create();
dsVScrollNone = createDS<Person>().onTrigger( () => this.datasource.getPeople(0, 3) ).create();

constructor(private datasource: DemoDataSource) { }
}
/* @pebula-example:ex-1 */
@@ -0,0 +1,3 @@
<docsi-bt-source-code-ref file="./reuse.component.ts" [section]='["ex-1"]'></docsi-bt-source-code-ref>
<docsi-bt-source-code-ref file="./reuse.component.md" lang="html" [section]='["ex-1"]'></docsi-bt-source-code-ref>
<docsi-bt-compile-markdown src="./reuse.component.md"></docsi-bt-compile-markdown>
@@ -0,0 +1,49 @@
# Table Re-Use

Reusing of a table refers to changing the model that the table represents.

Looking at the following column factory the model is quite clear:

```typescript
columnFactory()
.table(
{ prop: 'id' },
{ prop: 'name' },
{ prop: 'email' },
)
.build();
```

For this column definition set, the table expects a similar collection of objects returned from the data source.

The datasource is dynamic, returning values per demand.

```typescript
createDS<Person>()
.onTrigger( (event) => [ { id: 1, name: 'John', email: 'N/A' }] )
.create();
```

Now, if we want to apply a different model on the table? We will have to change the column definition set as well at the datasource.

In the following example the table can toggle between showing a **Person** model or a **Seller** model.

<docsi-mat-example-with-source title="Re-Use" contentClass="table-height-300 mat-elevation-z7" [query]="[{section: 'ex-1'}]">
<!--@pebula-example:ex-1-->
<pbl-ngrid blockUi usePagination [dataSource]="dynamicColumnsDs" [columns]="dynamicColumns">
<pbl-ngrid-paginator *pblNgridPaginatorRef="let table"
[table]="table"
[paginator]="table.ds.paginator"></pbl-ngrid-paginator>
</pbl-ngrid>
<!--@pebula-example:ex-1-->
</docsi-mat-example-with-source>

<button (click)="toggleViewMode()">{{ viewMode }}</button>

When we toggle, notice that we swap the entire datasource. We could have implemented the logic inside the `onTrigger` handler and keep a single datasource but it will not work.

When we swap a datasource the table will cleanup the context and all column related data and rebuilt it preventing ghost context living in the cache.

I> When a table gets destroyed (`ngOnDestroy`) the datasource attached to it (if attached) is disconnected and automatically disposed. This has 1 exception, the `keepAlive` configuration was enabled on the datasource.

W> When you swap the datasource it will also cause the previous datasource to disconnect, if `keepAlive` is `false` it will also dispose itself.
Empty file.
@@ -0,0 +1,81 @@
/* @pebula-example:ex-1 */
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { createDS, columnFactory } from '@pebula/ngrid';

import { Seller, Person, DemoDataSource } from '@pebula/apps/ngrid/shared';

function buildColumns(mode: 'person' | 'seller') {
if (mode === 'person') {
return columnFactory()
.table(
{ prop: 'id', sort: true, width: '40px' },
{ prop: 'name', sort: true },
{ prop: 'gender', width: '50px' },
{ prop: 'birthdate', type: 'date' },
{ prop: 'bio' },
{ prop: 'email', minWidth: 250, width: '250px' },
{ prop: 'language', headerType: 'language' },
)
.build();
} else {
return columnFactory()
.table(
{ prop: 'id', sort: true, width: '40px', wontBudge: true },
{ prop: 'name', sort: true },
{ prop: 'email', minWidth: 250, width: '150px' },
{ prop: 'address' },
{ prop: 'rating', type: 'starRatings', width: '120px' }
)
.build();
}
}

function createSource(mode: 'person' | 'seller', datasource: DemoDataSource) {
if (mode === 'person') {
return createDS<Person>().onTrigger(() => {
return datasource.getPeople(1000, 15);
}).create();
} else {
return createDS<Seller>().onTrigger(() => {
return datasource.getSellers(1000, 15)
}).create();
}
};

@Component({
selector: 'pbl-reuse-grid-example-component',
templateUrl: './reuse.component.html',
styleUrls: ['./reuse.component.scss'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ReuseGridExampleComponent {


dynamicColumns;
dynamicColumnsDs = createDS<Person | Seller>().onTrigger(() => {
if (this.viewMode === 'person') {
return this.datasource.getPeople(1000, 15);
} else {
return this.datasource.getSellers(1000, 15)
}
}).create();

columns = buildColumns('person');
ds2 = createDS<Person>().onTrigger( () => this.datasource.getPeople(0, 15) ).create();
ds3 = createDS<Person>().onTrigger( () => this.datasource.getPeople(0, 15) ).create();

viewMode: 'person' | 'seller' = 'person';

constructor(private datasource: DemoDataSource) {
this.toggleViewMode();
}

toggleViewMode(): void {
this.viewMode = this.viewMode === 'person' ? 'seller' : 'person';
this.dynamicColumnsDs = createSource(this.viewMode, this.datasource);
this.dynamicColumns = buildColumns(this.viewMode);
this.dynamicColumnsDs.refresh();
}
}
/* @pebula-example:ex-1 */
Expand Up @@ -21,11 +21,14 @@ import { PblNgridTransposeModule } from '@pebula/ngrid/transpose';
import { PblNgridBlockUiModule } from '@pebula/ngrid/block-ui';
import { PblNgridDetailRowModule } from '@pebula/ngrid/detail-row';
import { PblNgridStickyModule } from '@pebula/ngrid/sticky';
import { PblNgridMaterialModule } from '@pebula/ngrid-material';

import { SharedModule, ExampleGroupRegistryService } from '@pebula/apps/ngrid/shared';
import { ReuseGridExampleComponent } from './reuse/reuse.component';
import { RowHeightGridExampleComponent } from './row-height/row-height.component';
import { NoDataGridExampleComponent } from './no-data';
import { VirtualScrollGridExampleComponent } from './virtual-scroll/virtual-scroll.component';
import { FillerGridExampleComponent } from './filler/filler.component';

const MATERIAL = [
MatProgressSpinnerModule,
Expand All @@ -42,15 +45,19 @@ const MATERIAL = [
];

const DECLARATION = [
ReuseGridExampleComponent,
RowHeightGridExampleComponent,
NoDataGridExampleComponent,
VirtualScrollGridExampleComponent,
FillerGridExampleComponent,
];

const ROUTES = [
{ path: 'reuse', component: ReuseGridExampleComponent, data: { title: 'Re-Use' } },
{ path: 'row-height', component: RowHeightGridExampleComponent, data: { title: 'Row Height' } },
{ path: 'no-data', component: NoDataGridExampleComponent, data: { title: 'No Date' } },
{ path: 'virtual-scroll', component: VirtualScrollGridExampleComponent, data: { title: 'Virtual Scroll' } },
{ path: 'filler', component: FillerGridExampleComponent, data: { title: 'Filler' } },
];

@NgModule({
Expand All @@ -66,6 +73,7 @@ const ROUTES = [
PblNgridTransposeModule,
PblNgridDetailRowModule,
PblNgridStickyModule,
PblNgridMaterialModule,
],
exports: [ MatRippleModule ], // we need this for detail-row
providers: [ PblNgridRegistryService ],
Expand Down
Expand Up @@ -15,8 +15,11 @@ Here is the final result:

<docsi-mat-example-with-source title="Action Row" contentClass="table-height-300 mat-elevation-z7" [query]="[{section: 'ex-1'}]">
<!--@pebula-example:ex-1-->
<pbl-ngrid blockUi [dataSource]="ds1" [columns]="columns">
<pbl-ngrid blockUi [dataSource]="ds1" [columns]="columns" usePagination>
<my-table-action-row filter label="My Table"></my-table-action-row>
<pbl-ngrid-paginator *pblNgridPaginatorRef="let table"
[table]="table"
[paginator]="table.ds.paginator"></pbl-ngrid-paginator>
</pbl-ngrid>
<!--@pebula-example:ex-1-->
</docsi-mat-example-with-source>
Expand Down
2 changes: 1 addition & 1 deletion libs/ngrid-material/package.json
@@ -1,6 +1,6 @@
{
"name": "@pebula/ngrid-material",
"version": "1.0.0-alpha.4",
"version": "1.0.0-alpha.5",
"peerDependencies": {
"@angular/common": "^7.0.0",
"@angular/core": "^7.0.0",
Expand Down
5 changes: 4 additions & 1 deletion libs/ngrid/detail-row/src/lib/detail-row/row.ts
Expand Up @@ -97,7 +97,10 @@ export class PblNgridDetailRowComponent extends PblNgridRowComponent implements
if (this.opened) {
this._element.classList.add('pbl-row-detail-opened');
}
this.plugin.detailRowToggled(this);

const event = Object.create(this);
Object.defineProperty(event, 'row', { value: this.detailRow });
this.plugin.detailRowToggled(event);
}
}

Expand Down
2 changes: 1 addition & 1 deletion libs/ngrid/package.json
@@ -1,6 +1,6 @@
{
"name": "@pebula/ngrid",
"version": "1.0.0-alpha.4",
"version": "1.0.0-alpha.5",
"peerDependencies": {
"@angular/common": "^7.0.0",
"@angular/core": "^7.0.0",
Expand Down
4 changes: 2 additions & 2 deletions libs/ngrid/src/index.ts
Expand Up @@ -51,9 +51,9 @@ export {
PblNgridPlugin,
PblNgridPluginExtension,
PblNgridOnInitEvent,
PblNgridOnResizeRowtEvent,
PblNgridOnResizeRowEvent,
PblNgridOnInvalidateHeadersEvent,
PblNgridOnDataSourcetEvent,
PblNgridOnDataSourceEvent,
PblNgridEvents,
} from './lib/ext/types';

Expand Down

0 comments on commit c06bc17

Please sign in to comment.