Skip to content

Commit

Permalink
Merge pull request #76 from dkamburov/master
Browse files Browse the repository at this point in the history
Implement nested Column and Feature directives for IgGrid
  • Loading branch information
kdinev authored Aug 29, 2016
2 parents 8e3914e + c05b173 commit cf9f35a
Show file tree
Hide file tree
Showing 6 changed files with 319 additions and 10 deletions.
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ <h2>Samples</h2>
<ul class="dropdown-menu" role="menu">
<li><a href="samples/igGrid/igGrid.html">Default</a></li>
<li><a href="samples/igGrid-TopLevelOpts/igGrid-TopLevelOpts.html">Top-level template options</a></li>
<li><a href="samples/igGrid-ComplexOpts/igGrid-ComplexOpts.html">Complex template options</a></li>
</ul>
</div>
<a class="btn btn-default" href="samples/igHierarchicalGrid/igHierarchicalGrid.html">igHierarchicalGrid</a>
Expand Down
44 changes: 44 additions & 0 deletions samples/igGrid-ComplexOpts/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {Component, Directive, Inject, ElementRef, EventEmitter, HostListener} from '@angular/core';
import {IgGridComponent, Column, Feature} from "../../src/igniteui.angular2.ts";
import {Northwind} from "./../data/northwind.ts";
import {bootstrap } from '@angular/platform-browser-dynamic';
import {FORM_DIRECTIVES} from '@angular/common';

declare var jQuery: any;

@Component({
selector: 'my-app',
templateUrl: "./igGrid-ComplexOptsTemplate.html",
directives: [FORM_DIRECTIVES, IgGridComponent, Column, Feature ]
})
export class AppComponent {
private cols: Array<any>;
private id: string;
private data: any;
private w: string;
private h: string;
private pKey: string;
private isReadOnly: boolean = true;
private cs: Array<any> = [{columnKey: "ProductID", readOnly: this.isReadOnly}];
private pi: number = 0;
private idHeaderText: string = "Id";
private pages: Array<number> = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

constructor() {
this.data = Northwind.getData();

this.id ='grid1';
this.w = '100%';
this.h = '400px';
this.pKey = 'ProductID';

this.cols = [
{ key: "ProductID", headerText: "Product ID", width:"50px", dataType:"number" },
{ key: "ProductName", headerText: "Name", width:"250px", dataType:"string" },
{ key: "QuantityPerUnit", headerText: "Quantity per unit", width:"250px", dataType:"string" },
{ key: "UnitPrice", headerText: "Unit Price", width:"100px", dataType:"number" }
];
}
}

bootstrap(AppComponent);
82 changes: 82 additions & 0 deletions samples/igGrid-ComplexOpts/igGrid-ComplexOpts.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<!DOCTYPE html>
<html>
<head>
<title>Angular 2 IgniteUI custom component</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" type="text/css" />
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" type="text/css" />
<link href="http://cdn-na.infragistics.com/igniteui/latest/css/themes/infragistics/infragistics.theme.css" rel="stylesheet" type="text/css" />
<link href="http://cdn-na.infragistics.com/igniteui/latest/css/structure/infragistics.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="../sample.css" />

</head>
<body class="container">

<div class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Ignite UI Angular 2 components <span class="badge alert-info">Preview</span></a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/igniteui-angular2/index.html">Home</a></li>
<li><a href="https://github.com/IgniteUI/igniteui-angular2">View on GitHub <i class="fa fa-github"></i></a></li>
</ul>
</div>
</div>
</div>
<div>
<h1 class="push-down-md"><a href="http://igniteui.com/grid/overview" target="_blank">igGrid</a></h1>

<div class="row description">
<div class="col-md-12">
<p class="lead">This sample demonstrates how AngularJS components are used to initialize the igGrid complex options though the template.</p>
<p><a href="https://github.com/IgniteUI/igniteui-angular2/blob/master/samples/igGrid/igGrid.html" class="btn btn-default btn-lg btn-primary" target="_blank"><i class="fa fa-code fa-lg"></i> Explore the Code</a></p>
</div>
</div>

<my-app>Loading...</my-app>


</div>
<footer>
<p>
<a href="/igniteui-angular2/index.html">Home</a> |
<a href="https://github.com/IgniteUI/igniteui-angular2/issues">Feedback &amp; Questions</a> |
<a href="https://github.com/IgniteUI/igniteui-angular2">Clone &amp; Fork</a>
</p>
<p class="small">For more information or to download a trial of Ignite UI, please visit: <a href="http://www.igniteui.com">http://www.igniteui.com</a></p>
</footer>

<!-- 1. Load libraries -->
<script src="http://code.jquery.com/jquery-1.12.3.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.min.js"></script>
<!-- IE required polyfills, in this exact order -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.0/es6-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.20/system-polyfills.js"></script>
<script src="https://npmcdn.com/angular2/es6/dev/src/testing/shims_for_IE.js"></script>

<script src="https://npmcdn.com/[email protected]?main=browser"></script>
<script src="https://npmcdn.com/[email protected]/lib/typescript.js"></script>
<script src="https://npmcdn.com/[email protected]"></script>
<script src="https://npmcdn.com/[email protected]/dist/system.src.js"></script>
<script src="./../../systemjs.config.js"></script>
<!-- Ignite UI Required Combined JavaScript Files -->
<script src="http://cdn-na.infragistics.com/igniteui/latest/js/infragistics.core.js"></script>
<script src="http://cdn-na.infragistics.com/igniteui/latest/js/infragistics.lob.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script>
System.import('app.ts')
.then(null, console.error.bind(console));
</script>
</body>
</html>
20 changes: 20 additions & 0 deletions samples/igGrid-ComplexOpts/igGrid-ComplexOptsTemplate.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div class="row">
<div class="col-md-12">
<ig-grid [widgetId]='id' [width]='w' [autoCommit]='true' [dataSource]='data' [height]='h' [autoGenerateColumns]='false' [primaryKey]='"ProductID"'>
<column [key]="'ProductID'" [(headerText)]="idHeaderText" [width]="'165px'" [dataType]="'number'"></column>
<column [key]="'ProductName'" [headerText]="'Product Name'" [width]="'250px'" [dataType]="'string'"></column>
<column [key]="'QuantityPerUnit'" [headerText]="'Quantity per unit'" [width]="'250px'" [dataType]="'string'"></column>
<column [key]="'UnitPrice'" [headerText]="'Unit Price'" [width]="'100px'" [dataType]="'number'"></column>
<feature [name]="'Paging'" [(currentPageIndex)]="pi" [pageSize]="'2'"></feature>
</ig-grid>

<br>
<label for="pageIndex">Current Page Index:</label>
<select [(ngModel)]="pi" name="pageIndex">
<option *ngFor="let i of pages">{{i}}</option>
</select>
<br>
<label for="headerText">First column header text:</label><input name="headerText" [(ngModel)]="idHeaderText">{{idHeaderText}}
</div>

</div>
145 changes: 136 additions & 9 deletions src/igniteui.angular2.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Component, Directive, Inject, ElementRef, EventEmitter, Output, Input, Query, QueryList, Renderer, OnChanges, NgZone,
SimpleChange, ChangeDetectionStrategy, IterableDiffers, DoCheck, Optional} from '@angular/core';
SimpleChange, ChangeDetectionStrategy, IterableDiffers, DoCheck, Optional, ContentChildren, AfterContentInit} from '@angular/core';
import {NgModel, ControlValueAccessor} from '@angular/common';

declare var jQuery: any;
Expand Down Expand Up @@ -46,6 +46,118 @@ var NODES = {
"ig-tile-manager": "div"
};

module IgUtil {
export function extractAllGridFeatureOptions() {
let allWidgets = jQuery.ui;
let options = ['name'];
let widget: any;
for (widget in allWidgets) {
if (widget.substring(0, 6) === "igGrid" && widget !== "igGrid") {
options = options.concat(Object.keys(jQuery.ui[widget].prototype.options));
}
}
return options;
}

export function extractAllGridColumnProperties() {
return ['headerText', 'key', 'formatter', 'format', 'dataType', 'width', 'hidden', 'template', 'unbound', 'group', 'rowspan', 'formula', 'unboundValues', 'unboundValuesUpdateMode', 'headerCssClass', 'columnCssClass'];
}
}

@Directive({
selector: 'column',
inputs: IgUtil.extractAllGridColumnProperties()
})
export class Column {
public _settings: any = {};
private _el: any;

constructor(el: ElementRef) {
this._el = el;
let self = this;
let i, settings = IgUtil.extractAllGridColumnProperties();
for(i = 0; i < settings.length; i++) {
Object.defineProperty(self, settings[i], {
set: self.createColumnsSetter(settings[i]),
get: self.createColumnsGetter(settings[i]),
enumerable: true,
configurable: true
});
}
}

createColumnsSetter(name) {
return function (value) {
let grid = jQuery(this._el.nativeElement.parentElement).find("table[role='grid']");
this._settings[name] = value;

if (jQuery.ui["igGrid"] &&
jQuery.ui["igGrid"].prototype.options &&
jQuery.ui["igGrid"].prototype.options.hasOwnProperty("columns") &&
grid.data("igGrid")) {
grid["igGrid"]("option", "columns", this._settings);
}
}
}

createColumnsGetter(name) {
return function () {
return this._settings[name];
}
}
}

@Directive({
selector: 'feature',
inputs: IgUtil.extractAllGridFeatureOptions()
})

export class Feature {
private _el: any;
public _settings: any = {};
public initSettings: {};
private name: string;

constructor(el: ElementRef) {
this._el = el;
}

ngOnInit() {
var self = this;
this.initSettings = jQuery.extend(true, {}, this);
let featureName = "igGrid" + this.name;
for (var setting in jQuery.ui[featureName].prototype.options) {
Object.defineProperty(self, setting, {
set: self.createFeatureSetter(setting),
get: self.createFeatureGetter(setting),
enumerable: true,
configurable: true
});
}
}

createFeatureSetter(name) {
return function (value) {
let grid = jQuery(this._el.nativeElement.parentElement).find("table[role='grid']");
let featureName = "igGrid" + this.name;
this._settings[name] = value;

if (jQuery.ui[featureName] &&
jQuery.ui[featureName].prototype.options &&
jQuery.ui[featureName].prototype.options.hasOwnProperty(name) &&
grid.data(featureName)) {
grid[featureName]("option", name, value);
}
}
}

createFeatureGetter(name) {
return function () {
return this._settings[name];
}
}
}

export function IgComponent(args: any = {}) {

return function (cls) {
Expand All @@ -66,7 +178,7 @@ export function IgComponent(args: any = {}) {
});

var evt = [];
var opts = [];
var opts = ["options", "widgetId", "changeDetectionInterval"];
if (jQuery.ui[contrName]) {
for (var propt in jQuery.ui[contrName].prototype.events) {
evt.push(propt);
Expand All @@ -86,16 +198,16 @@ export function IgComponent(args: any = {}) {
}

export class IgControlBase<Model> implements DoCheck {
private _opts: any = {};
private _differs: any;
protected _opts: any = {};
protected _el: any;
protected _widgetName: string;
protected _differ: any;
protected _config: any;
protected _events: Map<string, string>;
protected _allowChangeDetection = true;

@Input() set options(v: Model) {
set options(v: Model) {
this._config = jQuery.extend(true, v, this._opts);
if (this._opts.dataSource) {
// _config.dataSource should reference the data if the data is set as a top-level opts
Expand All @@ -108,8 +220,8 @@ export class IgControlBase<Model> implements DoCheck {
delete this._opts.dataSource;
}
};
@Input() widgetId: string;
@Input() changeDetectionInterval: number;
public widgetId: string;
public changeDetectionInterval: number;

constructor(el: ElementRef, renderer: Renderer, differs: IterableDiffers) {
this._differs = differs;
Expand All @@ -132,11 +244,13 @@ export class IgControlBase<Model> implements DoCheck {
createSetter(name) {
return function (value) {
this._opts[name] = value;
if (this._config) {
this._config[name] = value;
}
if (jQuery.ui[this._widgetName] &&
jQuery.ui[this._widgetName].prototype.options &&
jQuery.ui[this._widgetName].prototype.options.hasOwnProperty(name) &&
jQuery(this._el).data(this._widgetName)) {
this._config[name] = value;
jQuery(this._el)[this._widgetName]("option", name, value);
}
}
Expand Down Expand Up @@ -300,15 +414,28 @@ export class IgControlBase<Model> implements DoCheck {
}
}

export class IgGridBase<Model> extends IgControlBase<Model> {
export class IgGridBase<Model> extends IgControlBase<Model> implements AfterContentInit {
protected _dataSource: any;
protected _changes: any;
@ContentChildren(Column) _columns: QueryList<Column>;
@ContentChildren(Feature) _features: QueryList<Feature>;

constructor(el: ElementRef, renderer: Renderer, differs: IterableDiffers) { super(el, renderer, differs); }

ngOnInit() {
this._dataSource = this._opts.dataSource ?
JSON.parse(JSON.stringify(this._opts.dataSource)) :
JSON.parse(JSON.stringify(this._config.dataSource));
}

ngAfterContentInit() {
if (this._columns.length) {
this._opts["columns"] = this._columns.map((c) => c._settings);
}
if (this._features.length) {
this._opts["features"] = this._features.map((c) => c.initSettings);
}
super.ngOnInit();
this._dataSource = JSON.parse(JSON.stringify(this._config.dataSource));
}

deleteRow(id) {
Expand Down
Loading

0 comments on commit cf9f35a

Please sign in to comment.