Back

Dynamic columns

In this example you can modify columns inside the gui-grid by using forms positioned on the right side of the page.

The first form enables you a possibility to add column to the grid. For that purpose you have to define it by using two input values: column header and field and click the Add column button.

The second form gives an option to edit columns inside the grid or remove them. Select specifies existing column headers. Whereas, inside the input area you can change column attributes such as: header name, column field, column width. Please note, that not every column has predefined width. Moreover, available column fields are: index, character, name, abilities.

Source code of this example is at the bottom of the page.
Add column
Edit column
  • Select column field
  • Select column header
  • Select column field

Source code

app.component.html
app.component.ts
add-column.component.ts
edit-column.component.ts
dc-data.service.ts
dc-data.ts
<section class="tw-grid tw-grid-cols-auto-fit-330 tw-gap-4 tw-mt-8">

	<div class="tw-col-span-2 lg:tw-col-span-1 tw-mb-8">

		<gui-grid *ngIf="isBrowser"
				  [maxHeight]="400"
				  [columns]="columns"
				  [paging]="paging"
				  [source]="source">
		</gui-grid>

	</div>

	<div class="tw-max-w-sm">
		<gui-tab [active]="'Add column'"
				 [menu]="['Add column','Edit column']">

			<gui-tab-item [tab]="'Add column'">
				<gw-example-dynamic-column-add-column [fieldList]="fieldList"
													  (onAddColumn)="addColumn($event)">
				</gw-example-dynamic-column-add-column>
			</gui-tab-item>

			<gui-tab-item [tab]="'Edit column'">
				<gw-example-dynamic-column-edit-column [fieldList]="fieldList"
													   [headerList]="headerList"
													   [columns]="columns"
													   (onEditColumn)="editColumn($event)"
													   (onRemoveColumn)="removeColumn($event)">

				</gw-example-dynamic-column-edit-column>
			</gui-tab-item>

		</gui-tab>
	</div>

</section>
import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core';

import { DcDataService } from '../../dc/data/dc-data.service';
import { GuiColumn, GuiPaging, GuiPagingDisplay } from '@generic-ui/ngx-grid';
import { isPlatformBrowser } from '@angular/common';
import { GuiSelectOption } from '@generic-ui/fabric';
import { DcHero } from '../../dc/data/dc-hero';
import { Subscription } from 'rxjs';


@Component({
	selector: 'gw-example-dynamic-column-grid',
	templateUrl: './example-dynamic-column-grid.component.html',
	providers: [DcDataService]
})
export class ExampleDynamicColumnGridComponent implements OnInit, OnDestroy {

	source: Array<DcHero> = [];

	columns: Array<GuiColumn> = [{
		header: 'Character',
		field: 'character'
	}];

	paging: GuiPaging = {
		enabled: true,
		display: GuiPagingDisplay.ADVANCED
	};

	headerList: Array<GuiSelectOption> = this.createColumnHeaderList();

	fieldList: Array<GuiSelectOption> = [
		{ name: 'index', value: 'index' },
		{ name: 'character', value: 'character' },
		{ name: 'name', value: 'name' },
		{ name: 'abilities', value: 'abilities' }
	];

	isBrowser = false;

	subscription: Subscription;

	constructor(@Inject(PLATFORM_ID) private platformId: any,
				private dcDataService: DcDataService) {
		this.isBrowser = isPlatformBrowser(platformId);
	}

	ngOnInit() {
		this.subscription = this.dcDataService
								.getHeroes()
								.subscribe(heroes => {
									this.source = heroes;
								});
	}

	ngOnDestroy() {
		if (this.subscription) {
			this.subscription.unsubscribe();
		}
	}

	addColumn(post: { string, columnField: string }): void {
		const column = {
			header: post.columnHeader,
			field: post.columnField
		};

		this.columns = [
			...this.columns,
			column
		];
		this.headerList = this.createColumnHeaderList();
	}

	removeColumn(headerName: string): void {
		const columns = [...this.columns];

		for (let i = 0; i < this.columns.length; i++) {
			if (this.columns[i].header === headerName) {
				columns.splice(i, 1);
				this.columns = [...columns];
			}
		}
		this.headerList = this.createColumnHeaderList();
	}

	editColumn(post: {
		string,
		columnField: string,
		columnWidth: string,
		selectedHeader: string
	}): void {
		const columns = [...this.columns];

		for (let i = 0; i < this.columns.length; i++) {
			if (this.columns[i].header === post.selectedHeader) {
				this.columns[i].header = post.columnHeader;
				this.columns[i].field = post.columnField;
				this.columns[i].width = post.columnWidth;
				this.columns = [...columns];
			}
		}

		this.headerList = this.createColumnHeaderList();
	}

	private createColumnHeaderList(): Array<GuiSelectOption> {
		const list = [];

		for (let i = 0; i < this.columns.length; i++) {
			list.push(this.columns[i].header);
		}
		return list.map((headerElement: string) => {
			return { name: headerElement, value: headerElement };
		});
	}
}
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
import { GuiSelectOption } from '@generic-ui/fabric';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
	selector: 'gw-example-dynamic-column-add-column',
	template: `
		<form [formGroup]="form"
			  (ngSubmit)="addColumn()"
			  class="tw-mt-6">
			<div class="tw-mb-5 tw-px-8">
				<ul class="tw-list-none tw-p-0">

					<li class="tw-mb-6">

						<label for="columnHeader" class="tw-text-sm">
							Column header:
						</label>

						<input gui-input
							   formControlName="columnHeader"
							   id="columnHeader"
							   class="tw-w-64">

					</li>

					<li class="tw-mb-6">

						<label class="tw-text-sm">
							Column field
						</label>

						<gui-select [options]="fieldList"
									[width]="220"
									[placeholder]="'Select column field'"
									(optionChanged)="selectField($event)">
						</gui-select>

					</li>

					<li>
						<button [disabled]="!form.valid" gui-button type="submit">Add column</button>
					</li>
				</ul>
			</div>
		</form>
	`,
	encapsulation: ViewEncapsulation.None,
	changeDetection: ChangeDetectionStrategy.OnPush
})
export class ExampleDynamicColumnAddColumn {

	@Input()
	fieldList: Array<GuiSelectOption>;

	@Output()
	onAddColumn = new EventEmitter();

	form: FormGroup;

	selectedField: GuiSelectOption;

	constructor(private formBuilder: FormBuilder) {
		this.form = formBuilder.group({
			'columnHeader': ['', Validators.required],
			'columnField': ['', Validators.required]
		});
	}

	selectField(option: GuiSelectOption): void {
		this.selectedField = { name: option.name, value: option.name };
		this.form.get('columnField').setValue(option.name);
	}

	addColumn(): void {
		if (this.form.valid) {
			this.onAddColumn.emit(this.form.value);
			this.form.reset();
		}
	}
}
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
import { GuiSelectOption } from '@generic-ui/fabric';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { GuiColumn } from '@generic-ui/ngx-grid';

@Component({
	selector: 'gw-example-dynamic-column-edit-column',
	template: `
		<form [formGroup]="form"
			  (ngSubmit)="editColumn()"
			  class="tw-mt-6">
			<div class="tw-mb-5 tw-px-8">
				<ul class="tw-list-none tw-p-0">

					<li class="tw-mb-6">

						<label>Selected column:</label>
						<gui-select [options]="headerList"
									[placeholder]="'Select column header'"
									[selected]="selectedHeader"
									[width]="220"
									(optionChanged)="selectColumn($event)">
						</gui-select>

					</li>
					<li class="tw-mb-6">

						<label for="editedColumnHeader" class="tw-text-sm">
							Column header
						</label>

						<input gui-input
							   formControlName="columnHeader"
							   id="editedColumnHeader"
							   class="tw-w-64">

					</li>
					<li class="tw-mb-6">

						<label class="tw-text-sm">
							Column field
						</label>

						<gui-select [options]="fieldList"
									[width]="220"
									[placeholder]="'Select column field'"
									[selected]="selectedField"
									(optionChanged)="selectField($event)">
						</gui-select>

					</li>
					<li class="tw-mb-6">

						<label for="editedColumnWidth" class="tw-text-sm">
							Column width:
						</label>

						<input gui-input
							   formControlName="columnWidth"
							   id="editedColumnWidth"
							   class="tw-w-64">

					</li>

					<li class="tw-mb-6">
						<button [disabled]="!form.valid || !selectedHeader"
								gui-button
								type="submit"
								class="tw-mr-3">
							Edit
						</button>
						<button (click)="removeColumn()"
								[disabled]="!selectedHeader"
								gui-button>
							Remove
						</button>
					</li>

				</ul>
			</div>
		</form>
	`,
	encapsulation: ViewEncapsulation.None,
	changeDetection: ChangeDetectionStrategy.OnPush
})
export class ExampleDynamicColumnEditColumn {

	@Input()
	columns: Array<GuiColumn>;

	@Input()
	fieldList: Array<GuiSelectOption>;

	@Input()
	headerList: Array<GuiSelectOption>;

	@Output()
	onEditColumn = new EventEmitter();

	@Output()
	onRemoveColumn = new EventEmitter();

	form: FormGroup;

	selectedField: GuiSelectOption;

	selectedHeader: GuiSelectOption;

	constructor(private formBuilder: FormBuilder) {
		this.form = formBuilder.group({
			'columnHeader': ['', Validators.required],
			'columnField': ['', Validators.required],
			'columnWidth': ''
		});
	}

	selectField(option: GuiSelectOption): void {
		this.selectedField = { name: option.name, value: option.name };
		this.form.get('columnField').setValue(option.name);
	}

	selectColumn(option: GuiSelectOption): void {
		this.selectedHeader = option;

		for (let i = 0; i < this.columns.length; i++) {
			if (this.columns[i].header === this.selectedHeader.name) {
				this.form.get('columnHeader').setValue(this.columns[i].header);
				this.form.get('columnWidth').setValue(this.columns[i].width);
				this.selectField({ name: this.columns[i].field.toString() });
			}
		}
	}

	editColumn(): void {
		if (this.form.valid) {
			this.onEditColumn.emit({
				...this.form.value,
				selectedHeader: this.selectedHeader.name
			});
		}
	}

	removeColumn(): void {
		this.onRemoveColumn.emit(this.selectedHeader.name);
	}
}
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { HEROES } from './dc-data';
import { DcHero } from './dc-hero';

@Injectable()
export class DcDataService {

	private heroes$ = new BehaviorSubject(HEROES);

	getHeroes(): Observable<Array<DcHero>> {
		return this.heroes$.asObservable();
	}
}
export const HEROES = [
	{
		index: '1',
		character: 'Batman',
		name: 'Bruce Wayne',
		abilities: 'money'
	}, {
		index: '2',
		character: 'Flash',
		name: 'Barry Allen',
		abilities: 'speed'
	}, {
		index: '3',
		character: 'Superman',
		name: 'Clark Kent',
		abilities: 'invincible'
	}, {
		index: '4',
		character: 'Wonder Woman',
		name: 'Diana Prince',
		abilities: 'superhuman strength'
	}, {
		index: '5',
		character: 'Nightwing',
		name: 'Dick Grayson',
		abilities: 'martial arts'
	}, {
		index: '6',
		character: 'Green Lantern',
		name: 'Hal Jordan',
		abilities: 'Power ring'
	}, {
		index: '7',
		character: 'Green Arrow',
		name: 'Oliver Queen',
		abilities: 'money'
	}, {
		index: '8',
		character: 'Aquaman',
		name: 'Arthur Curry',
		abilities: 'can talk with fishes'
	}, {
		index: '9',
		character: 'Martian Manhunter',
		name: 'John Jones',
		abilities: 'telepathy'
	}, {
		index: '10',
		character: 'Captain Marvel',
		name: 'Billy Batson',
		abilities: 'superhuman abilities'
	}, {
		index: '11',
		character: 'Black Canary',
		name: 'Laurel Lance',
		abilities: 'sonic scream'
	}, {
		index: '12',
		character: 'Zatanna',
		name: 'Zatanna',
		abilities: 'magic'
	}, {
		index: '13',
		character: 'Robin',
		name: 'Damian Wayne',
		abilities: 'martial arts, gadgets'
	}, {
		index: '14',
		character: 'Supergirl',
		name: 'Kara Zor-El',
		abilities: 'superhuman powers'
	}, {
		index: '15',
		character: 'Batgirl',
		name: 'Barbara Gordon',
		abilities: 'speed, flexibility and strength'
	}, {
		index: '16',
		character: 'Cyborg',
		name: 'Vic Stone',
		abilities: 'high-tech gadgets'
	}, {
		index: '17',
		character: 'Kid Flash',
		name: 'Wally West',
		abilities: 'speed'
	}, {
		index: '18',
		character: 'Catwoman',
		name: 'Selina Kyle',
		abilities: 'stealthy and agile'
	}, {
		index: '19',
		character: 'Red Robin',
		name: 'Tim Drake',
		abilities: 'martial arts'
	}, {
		index: '20',
		character: 'John Constantine',
		name: 'John Constantine',
		abilities: 'sorcery'
	}, {
		index: '21',
		character: 'Raven',
		name: 'Rachel Roth',
		abilities: 'dark magic'
	}, {
		index: '22',
		character: 'Starfire',
		name: 'Koriand\'r',
		abilities: 'flight and energy projection'
	}, {
		index: '23',
		character: 'Beast Boy',
		name: 'Garfield Logan',
		abilities: 'shape-shifting'
	}, {
		index: '24',
		character: 'Hawkgirl',
		name: 'Kendra Saunders',
		abilities: 'flight'
	}, {
		index: '25',
		character: 'Doctor Fate',
		name: 'Kent Nelson',
		abilities: 'magic'
	}, {
		index: '26',
		character: 'Red Hood',
		name: 'Jason Todd',
		abilities: 'martial arts'
	}, {
		index: '27',
		character: 'Firestorm',
		name: 'Ronnie Raymond / Martin Stein',
		abilities: 'nuclear power'
	}, {
		index: '28',
		character: 'The Atom',
		name: 'Ray Palmer',
		abilities: 'size-changing'
	}, {
		index: '29',
		character: 'Jonah Hex',
		name: 'Jonah Hex',
		abilities: 'excellent gunslinger'
	}, {
		index: '30',
		character: 'Joker',
		name: 'Clown Prince of Crime',
		abilities: 'deadly and unpredictable'
	}, {
		index: '31',
		character: 'Lex Luthor',
		name: 'Alexander Luthor',
		abilities: 'money'
	}, {
		index: '32',
		character: 'Darkseid',
		name: 'Darkseid',
		abilities: 'unparalleled strength'
	}, {
		index: '33',
		character: 'Sinestro',
		name: 'Thaal Sinestro',
		abilities: 'power ring'
	}, {
		index: '34',
		character: 'Brainiac',
		name: 'Vril Dox',
		abilities: 'Extremely advanced mental abilities'
	}, {
		index: '35',
		character: 'Black Adam',
		name: 'Teth-Adam',
		abilities: 'superhuman abilities'
	}, {
		index: '36',
		character: 'Ra\'s al Ghul',
		name: 'Head of the Demon',
		abilities: 'immortality'
	}, {
		index: '37',
		character: 'Deathstrok',
		name: 'Slade Wilson',
		abilities: 'enhanced strength, agility and intelligence'
	}, {
		index: '38',
		character: 'Two-Face',
		name: 'Harvey Dent',
		abilities: 'can flip coins'
	}, {
		index: '39',
		character: 'Vandal Savage',
		name: 'Vandal Savage',
		abilities: 'immortality'
	}, {
		index: '40',
		character: 'Reverse Flash',
		name: 'Eobard Thawne',
		abilities: 'speed'
	}, {
		index: '41',
		character: 'Doomsday',
		name: 'Doomsday',
		abilities: 'regenerative abilities'
	}, {
		index: '42',
		character: 'Mongul',
		name: 'Mongul I',
		abilities: 'superhuman abilities'
	}, {
		index: '43',
		character: 'Bizarro',
		name: 'Bizarro',
		abilities: 'has many duplicates'
	}, {
		index: '44',
		character: 'Riddler',
		name: 'Edward Nygma',
		abilities: 'excellent at creating riddles'
	}, {
		index: '45',
		character: 'Maxwell Lord',
		name: 'Maxwell Lord IV',
		abilities: 'mind control'
	}, {
		index: '46',
		character: 'Captain Cold',
		name: 'Leonard Snart',
		abilities: 'cold gun'
	}, {
		index: '47',
		character: 'Bane',
		name: 'Bane',
		abilities: 'good at taking steroid'
	}, {
		index: '48',
		character: 'Harley Quinn',
		name: 'Harleen Quinzel',
		abilities: 'spending money'
	}, {
		index: '49',
		character: 'Gorilla Grodd',
		name: 'Gorilla Grodd',
		abilities: 'super-intelligence'
	}, {
		index: '50',
		character: 'Lobo',
		name: 'Lobo',
		abilities: 'incredible strength and regeneration'
	}];