Skip to content

Commit

Permalink
Merge pull request #193 from damnko/custom-view-component
Browse files Browse the repository at this point in the history
Add custom cell view component
  • Loading branch information
lexzhukov authored Mar 2, 2017
2 parents 487dcdb + dd41cd0 commit 993aa3a
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { CustomEditorComponent } from './custom-editor.component';
import { CustomRenderComponent } from './custom-render.component';

@Component({
selector: 'advanced-example-custom-editor',
Expand Down Expand Up @@ -42,7 +43,9 @@ export class AdvancedExamplesCustomEditorComponent {
title: 'ID'
},
name: {
title: 'Full Name'
title: 'Full Name',
type: 'custom',
renderComponent: CustomRenderComponent
},
username: {
title: 'User Name',
Expand Down
18 changes: 18 additions & 0 deletions demo/src/app/pages/demo/components/custom-render.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Component, Input } from '@angular/core';

import { ViewCell } from '../../../../../../ng2-smart-table';

@Component({
template: `
{{renderValue}}
`
})
export class CustomRenderComponent implements ViewCell {

renderValue: string;
@Input() value: string | number;

ngOnInit() {
this.renderValue = this.value.toString().toUpperCase();
}
}
15 changes: 10 additions & 5 deletions demo/src/app/pages/demo/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ <h4>Navigation</h4>
<li><a href="#confirm">Confirm Action Example</a></li>
<li><a href="#server">Load From Server Example</a></li>
<li><a href="#types">Completer and other built-in editors</a></li>
<li><a href="#custom-editor">Using a custom editor</a></li>
<li><a href="#custom-editor-renderer">Using a custom editor or renderer</a></li>
<li><a href="#multiselect">Multi select</a></li>
<li><a href="#filters">Completer and other built-in filters</a></li>
</ul>
Expand Down Expand Up @@ -202,17 +202,22 @@ <h3><a id="types" class="anchor" href="#types" aria-hidden="true"><span aria-hid
<a class="source" href="https://github.com/akveo/ng2-smart-table/blob/master/demo/src/app/pages/demo/components/advanced-example-types.component.ts" target="_blank">Demo Source</a>
<advanced-example-types></advanced-example-types>
</div>
<h3><a id="custom-editor" class="anchor" href="#custom-editor" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Custom editor column type</h3>
<p>An example on how to use a custom editor during cell edit mode:</p>
<h3><a id="custom-editor-renderer" class="anchor" href="#custom-editor-renderer" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Custom editor/renderer column type</h3>
<p>An example on how to use a custom cell editor and/or custom cell renderer:</p>
<div class="with-source">
<a class="source" href="https://github.com/akveo/ng2-smart-table/blob/master/demo/src/app/pages/demo/components/advanced-example-custom-editor.component.ts" target="_blank">Demo Source</a>
<advanced-example-custom-editor></advanced-example-custom-editor>
</div>
<p>When implementing a custom editor remember to add it to the <code>entryComponents</code> and to the <code>declarations</code> part of your module</p>
<p>When implementing a custom editor or renderer remember to add it to the <code>entryComponents</code> and to the <code>declarations</code> part of your module</p>
<pre>
<code class="typescript">{{ snippets.customEditorModule }}</code>
</pre>
<p>To inherit the methods needed to interact with the table you can either extend the component with the <code>DefaultEditor</code> class or implement the <code>Editor</code> interface and reproduce the same methods on your component.</p>
<p>
<b>For the custom cell editor:</b><br>
To inherit the methods needed to interact with the table you can either extend the component with the <code>DefaultEditor</code> class or implement the <code>Editor</code> interface and reproduce the same methods on your component.<br>
<b>For the custom cell renderer:</b><br>
In this example the custom component is applying a <code>.toUpperCase()</code> to one of the columns. You can implement the ViewCell interface to make sure you are setting up your component correctly.
</p>
<h3><a id="multiselect" class="anchor" href="#multiselect" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Multi select</h3>
<p>An example on how to use multi select mode:</p>
<div class="with-source">
Expand Down
3 changes: 2 additions & 1 deletion demo/src/app/pages/demo/snippets/custom-editor-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
imports: [
// ...
],
entryComponents: [CustomEditorComponent],
entryComponents: [CustomEditorComponent, CustomRenderComponent],
declarations: [
// ...
CustomEditorComponent,
CustomRenderComponent,
],
})
17 changes: 14 additions & 3 deletions demo/src/app/pages/documentation/documentation.html
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,22 @@ <h3><a id="configuration" class="anchor" href="#configuration" aria-hidden="true
</tr>
<tr>
<td>type</td>
<td><span class="highlight">'text'</span>|<span class="highlight">'html'</span></td>
<td><span class="highlight">'text'</span>|<span class="highlight">'html'</span>|<span class="highlight">'custom'</span></td>
<td>'text'</td>
<td>
Column data type. NOTE: currently not fully supported.<br>
If type is <span class="highlight">html</span> then cell value will be inserted as html.
If type is <span class="highlight">text</span> then cell value will be inserted as text.<br>
If type is <span class="highlight">html</span> then cell value will be inserted as html.<br>
If type is <span class="highlight">custom</span> the <code>renderComponent</code> property must be defined.
</td>
</tr>
<tr>
<td>renderComponent</td>
<td><span class="highlight">any</span></td>
<td>null</td>
<td>
Custom component that will be responsible for rendering the cell content while in view mode.<br>
Type must be <span class="highlight">custom</span> in order for this to work.<br>
You can see an <a class="source" href="https://github.com/akveo/ng2-smart-table/blob/master/demo/src/app/pages/demo/components/advanced-example-custom-editor.component.ts">example here</a>
</td>
</tr>
<tr>
Expand Down
7 changes: 6 additions & 1 deletion demo/src/app/pages/pages.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { AdvancedExamplesTypesComponent } from './demo/components/advanced-examp
import { AdvancedExamplesCustomEditorComponent } from './demo/components/advanced-example-custom-editor.component';
import { AdvancedExampleFiltersComponent } from './demo/components/advanced-example-filters.component';
import { CustomEditorComponent } from './demo/components/custom-editor.component';
import { CustomRenderComponent } from './demo/components/custom-render.component';

@NgModule({
imports: [
Expand All @@ -32,7 +33,10 @@ import { CustomEditorComponent } from './demo/components/custom-editor.component
Ng2SmartTableModule,
routing,
],
entryComponents: [CustomEditorComponent],
entryComponents: [
CustomEditorComponent,
CustomRenderComponent,
],
declarations: [
DemoComponent,
DocumentationComponent,
Expand All @@ -49,6 +53,7 @@ import { CustomEditorComponent } from './demo/components/custom-editor.component
AdvancedExampleFiltersComponent,
ScrollPositionDirective,
CustomEditorComponent,
CustomRenderComponent,
],
})
export class PagesModule {
Expand Down
1 change: 1 addition & 0 deletions ng2-smart-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './src/ng2-smart-table/lib';
export * from './src/ng2-smart-table.module';
export { Cell } from './src/ng2-smart-table/lib/data-set/cell';
export { DefaultEditor, Editor } from './src/ng2-smart-table/components/cell/cell-editors/default-editor';
export { ViewCell } from './src/ng2-smart-table/components/cell/cell-view-mode';
5 changes: 4 additions & 1 deletion src/ng2-smart-table.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { Ng2CompleterModule } from 'ng2-completer';

import { NG2_SMART_TABLE_DIRECTIVES } from './ng2-smart-table.directives';
import { CellComponent } from './ng2-smart-table/components/cell/cell.component';
import { ViewCellComponent } from './ng2-smart-table/components/cell/cell-view-mode/view-cell.component';
import {
ViewCellComponent,
CustomViewComponent } from './ng2-smart-table/components/cell/cell-view-mode';
import {
EditCellComponent,
DefaultEditComponent,
Expand Down Expand Up @@ -38,6 +40,7 @@ import { NG2_SMART_TABLE_TBODY_DIRECTIVES } from './ng2-smart-table/components/t
ViewCellComponent,
DefaultEditComponent,
CustomEditComponent,
CustomViewComponent,
EditCellComponent,
CompleterEditorComponent,
InputEditorComponent,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {
Component,
Input,
ComponentFactoryResolver,
ViewChild,
ViewContainerRef,
OnInit,
OnDestroy } from '@angular/core';

import { Cell } from '../../../lib/data-set/cell';

@Component({
selector: 'custom-view-component',
template: `
<template #dynamicTarget></template>
`,
})
export class CustomViewComponent implements OnInit {

customComponent: any;
@Input() cell: Cell;
@ViewChild('dynamicTarget', {read: ViewContainerRef}) dynamicTarget: any;

constructor(private resolver: ComponentFactoryResolver) {
}

ngOnInit(): void {
if (this.cell && !this.customComponent){
let componentFactory = this.resolver.resolveComponentFactory(this.cell.getColumn().renderComponent);
this.customComponent = this.dynamicTarget.createComponent(componentFactory);

// set @Inputs and @Outputs of custom component
this.customComponent.instance.value = this.cell.getValue();
}
}

ngOnDestroy() {
if (this.customComponent) {
this.customComponent.destroy();
}
}
}
3 changes: 3 additions & 0 deletions src/ng2-smart-table/components/cell/cell-view-mode/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './custom-view.component';
export * from './view-cell.component';
export * from './view-cell';
Original file line number Diff line number Diff line change
@@ -1,34 +1,18 @@
import { Component, Input, ViewChild, ElementRef, OnChanges, AfterViewInit } from '@angular/core';
import { Component, Input, ViewChild, ElementRef } from '@angular/core';

import { Cell } from '../../../lib/data-set/cell';

@Component({
selector: 'table-cell-view-mode',
template: `
<div [ngSwitch]="cell.getColumn().type">
<div *ngSwitchCase="'html'" #cellContainer [innerHTML]="cell.getValue()"></div>
<div *ngSwitchDefault #cellContainer>{{ cell.getValue() }}</div>
<custom-view-component *ngSwitchCase="'custom'" [cell]="cell"></custom-view-component>
<div *ngSwitchCase="'html'" [innerHTML]="cell.getValue()"></div>
<div *ngSwitchDefault>{{ cell.getValue() }}</div>
</div>
`
})
export class ViewCellComponent implements OnChanges, AfterViewInit {
export class ViewCellComponent {

@Input() cell: Cell;
@ViewChild('cellContainer') cellRef: ElementRef;

ngOnChanges(changes): void {
setTimeout(() => this.renderCustomValue());
}

ngAfterViewInit(): void {
this.renderCustomValue();
}

renderCustomValue(): void {
const cellRenderFunc = this.cell.getColumn().getCellRenderFunction();

if (cellRenderFunc && this.cellRef)
cellRenderFunc.call(null, this.cell, this.cellRef.nativeElement);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface ViewCell {
value: string | number;
}
8 changes: 2 additions & 6 deletions src/ng2-smart-table/lib/data-set/column.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ export class Column {
public defaultSortDirection: string = '';
public editor: { type: string, config: any, component: any } = { type: '', config: {}, component: null };
public filter: { type: string, config: any } = { type: '', config: {} };
public renderComponent: any = null;
compareFunction: Function;
valuePrepareFunction: Function;
filterFunction: Function;
cellRenderFunction: Function;

constructor(public id: string, protected settings: any, protected dataSet: DataSet) {
this.process();
Expand All @@ -33,10 +33,6 @@ export class Column {
return this.filterFunction;
}

public getCellRenderFunction(): Function {
return this.cellRenderFunction;
}

public getConfig(): any {
return this.editor.config;
}
Expand All @@ -55,6 +51,7 @@ export class Column {
this.type = this.prepareType();
this.editor = this.settings['editor'];
this.filter = this.settings['filter'];
this.renderComponent = this.settings['renderComponent'];

this.isFilterable = typeof this.settings['filter'] === 'undefined' ? true : !!this.settings['filter'];
this.defaultSortDirection = ['asc', 'desc'].indexOf(this.settings['sortDirection']) !== -1 ? this.settings['sortDirection'] : '';
Expand All @@ -65,7 +62,6 @@ export class Column {
this.compareFunction = this.settings['compareFunction'];
this.valuePrepareFunction = this.settings['valuePrepareFunction'];
this.filterFunction = this.settings['filterFunction'];
this.cellRenderFunction = this.settings['cellRenderFunction'];
}

prepareType(): string {
Expand Down

0 comments on commit 993aa3a

Please sign in to comment.