First of all a great Framework..
I have two grids in my Index.cshtml both works fine Order and OrderDetails
I want to achieve the same scenario like in Northwind Example only without Dialog
Select Row in OrderGrid filters OrderDetailsGrid...
I think i need getSelectedRows and getDataItem but i am a beginner to TypeScript
I coud not get it to work... In Example onLoad i saw this
Does anyone have an example or point me to right direction
Thanks
You can use this method on the xyzGrid.ts to get the click event on the Grid.
And use getItems to retrieve the information of the row.
protected onClick(e: JQueryEventObject, row: number, cell: number): void {
let rowInformation = this.getItems()[row];
}
I recently had the same requirement. What I did was to create two base classes for re-usability, MasterGridBase and DetailGridBase.
export abstract class MasterGridBase<TItem> extends Serenity.EntityGrid<TItem, EntityGridOptions> {
protected grid: Slick.Grid;
protected rowSelection: Serenity.GridRowSelectionMixin;
onItemClicked: (item: TItem) => void;
onItemSelected: (item: TItem) => void;
onItemsSelected: (item: TItem[]) => void;
constructor(container: JQuery, options?: EntityGridOptions) {
super(container, options || {
selectionMode: 'single',
enableRowSelection: true
} as EntityGridOptions);
this.toolbar.element.attr('style', 'border-bottom: 1px solid #e7e7e7;margin-bottom: 4px;');
this.element.find('.title-text').prepend($(`<i class="${this.getGridIconClass()}"></i><span> </span>`));
}
private isMultiSelectEnabled() : boolean {
return this.options.enableRowSelection && this.options.selectionMode === 'multiple'
}
protected getGridIconClass() {
return 'fa icon-screen-desktop';
}
protected createToolbarExtensions() {
super.createToolbarExtensions();
if(this.isMultiSelectEnabled()) {
this.rowSelection = new Serenity.GridRowSelectionMixin(this);
}
}
protected getColumns() {
var columns = super.getColumns();
if (this.isMultiSelectEnabled()) {
columns.splice(0, 0, Serenity.GridRowSelectionMixin.createSelectColumn(() => this.rowSelection));
}
return columns;
}
public resetCheckedAndRefresh() {
if (this.isMultiSelectEnabled() && this.rowSelection != null) {
this.rowSelection.resetCheckedAndRefresh();
}
}
public getSelectedKeys() {
if (this.isMultiSelectEnabled() && this.rowSelection != null) {
return this.rowSelection.getSelectedKeys();
}
return [] as string[];
}
public getSelectedItems(): TItem[] {
let selectedKeys = this.getSelectedKeys();
if (selectedKeys != null && selectedKeys.length > 0) {
return selectedKeys.map(x => this.getView().getItemById(x));
}
return [] as TItem[];
}
public getSelectedItem(): TItem {
let items = this.getSelectedItems();
if (items != null && items.length > 0) {
return items[0];
}
return null as TItem;
}
protected getSlickOptions(): Slick.GridOptions {
var opt = super.getSlickOptions();
opt.enableCellNavigation = true;
opt.enableTextSelectionOnCells = true;
opt.selectedCellCssClass = "slick-row-selected";
return opt;
}
protected createSlickGrid(): Slick.Grid {
this.grid = super.createSlickGrid();
if(this.options.enableRowSelection) {
this.grid.setSelectionModel(new Slick.RowSelectionModel());
}
this.grid.onSelectedRowsChanged.subscribe((p1, selecion: { grid: Slick.Grid, rows:number[]}) => {
if (this.options.enableRowSelection) {
if (this.isMultiSelectEnabled() && this.rowSelection != null) {
let selectedKeys = this.getSelectedKeys();
if (this.onItemsSelected && selectedKeys != null && selectedKeys.length > 0) {
this.onItemsSelected(this.getSelectedItems());
}
} else if (this.onItemSelected && selecion.rows != null && selecion.rows.length > 0) {
this.onItemSelected(this.getView().getItemById(selecion.rows[0]));
}
}
});
return this.grid;
}
protected onClick(e: JQueryEventObject, row: number, cell: number): void {
super.onClick(e, row, cell);
let item = this.itemAt(row);
if (this.options.enableRowSelection && this.onItemClicked) {
this.onItemClicked(item as TItem);
}
}
public destroy() {
// clear to avoid memory holes
this.onItemClicked = null;
this.onItemSelected = null;
this.onItemsSelected = null;
super.destroy();
}
}
export interface EntityGridOptions {
enableRowSelection: boolean;
selectionMode: 'none' | 'single' | 'multiple';
}
export class DetailGridBase<TItem> extends EntityGridBase<TItem> {
private _masterItemID: string;
protected onMasterIdChanged(masterItemID: string) {}
get masterItemID() {
return this._masterItemID;
}
set masterItemID(value: string) {
if (this._masterItemID != value) {
this._masterItemID = value;
this.onMasterIdChanged(this._masterItemID);
this.setEquality(this.getMasterFieldName(), value);
this.refresh();
}
}
protected getMasterFieldName() {
return "";
}
protected getSlickOptions(): Slick.GridOptions {
var opt = super.getSlickOptions();
opt.rowHeight = 28;
return opt;
}
protected getGridCanLoad() {
return !Q.isEmptyOrNull(this.masterItemID);
}
}
export class StateGrid extends MasterGridBase<StateRow> {
protected getColumnsKey() { return 'Catalogs.State'; }
protected getDialogType() { return StateDialog; }
protected getIdProperty() { return StateRow.idProperty; }
protected getLocalTextPrefix() { return StateRow.localTextPrefix; }
protected getService() { return StateService.baseUrl; }
constructor(container: JQuery) {
super(container);
}
}
@Serenity.Decorators.registerClass()
export class LocalGovernmentGrid extends DetailGridBase<LocalGovernmentRow> {
protected getColumnsKey() { return 'Catalogs.LocalGovernment'; }
protected getDialogType() { return LocalGovernmentDialog; }
protected getIdProperty() { return LocalGovernmentRow.idProperty; }
protected getLocalTextPrefix() { return LocalGovernmentRow.localTextPrefix; }
protected getService() { return LocalGovernmentService.baseUrl; }
constructor(container: JQuery) {
super(container);
}
protected getMasterFieldName() {
return LocalGovernmentRow.Fields.StateId;
}
}
I have a Page.ts file that show usage bellow
export class CatalogsPage extends Serenity.TemplatedWidget<any> {
constructor(container: JQuery, options?: any) {
super(container, options);
this.stateGrid = new StateGrid(this.byId('State')).init();
this.localGovtGrid = new LocalGovernmentGrid(this.byId('LocalGovernment')).init();
this.stateGrid.onItemClicked = (item: StateRow) => {
if (item && item.Id) {
this.localGovtGrid.masterItemID = item.Id;
}
};
Q.initFullHeightGridPage(this.byId('State'));
Q.initFullHeightGridPage(this.byId('LocalGovernment'));
}
private stateGrid: StateGrid;
private localGovtGrid: LocalGovernmentGrid;
protected getTemplate(): string {
return `
<div id="~_Container">
<div class="col-md-6">
<section class="content" style="padding:5px;margin-bottom:10px">
<div id="~_State"></div>
</section>
</div>
<div class="col-md-6">
<section class="content" style="padding:5px;margin-bottom:10px">
<div id="~_LocalGovernment"></div>
</section>
</div>
</div>
`;
}
}
<div id="GridContainer"></div>
<script type="text/javascript">
jQuery(function () {
new CatalogsPage ($('#GridContainer'), {});
});
</script>
Place all classes within appropriate namespace and adjust the code accordingly.
I hope this helps. Serenity is a wonderful Platform but you must read the Developers Guide and read through Github Issues to wrap your head around its concepts. The only thing missing for me is composable UI (you cannot currently place Serenity Based widgets on pages with other html content without messing with less or css, EntityGrid is most guilty).
Any chance you can share code of : EntityGridBase ?
Most helpful comment
I recently had the same requirement. What I did was to create two base classes for re-usability, MasterGridBase and DetailGridBase.
MasterGridBase
DetailGridBase
Sample Usage
StateGrid
LocalGovernmentGrid
I have a Page.ts file that show usage bellow
Index.cshtml
Note:
Place all classes within appropriate namespace and adjust the code accordingly.
I hope this helps. Serenity is a wonderful Platform but you must read the Developers Guide and read through Github Issues to wrap your head around its concepts. The only thing missing for me is composable UI (you cannot currently place Serenity Based widgets on pages with other html content without messing with less or css, EntityGrid is most guilty).