Angular RxJS with DataGrid

Reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change. RxJS (Reactive Extensions for JavaScript) is a library for reactive programming using observables that makes it easier to compose asynchronous or callback-based code. In this blog post we will show how to use our Angular DataGrid component with RxJS.

angular datagrid rxjs observable

Observable creation functions

RxJS offers a number of functions that can be used to create new observables. These functions can simplify the process of creating observables from things such as events, timers, promises, and so on. For example

Using Smart.Grid with RxJS

In order to use our DataGrid with Angular and RxJS, you will need to do the following: 1. Create a new Angular project. 2. Install smart-webcomponents-angular vie npm install smart-webcomponents-angular or ng add smart-webcomponents-angular 3. Import the Smart.Grid module in app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { GridModule } from 'smart-webcomponents-angular/grid';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
    declarations: [ AppComponent ],
    imports: [ BrowserModule, FormsModule, GridModule, HttpClientModule ],
    bootstrap: [ AppComponent ],
	entryComponents: [ AppComponent ]
})

export class AppModule { }

4. Edit app.component.ts

import { Component, ViewChild, AfterViewInit, ViewEncapsulation } from '@angular/core';
import { GridComponent, GridColumn, DataAdapter, Smart } from 'smart-webcomponents-angular/grid';
import { GetData } from './data'
import { Observable, from  } from 'rxjs';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['app.component.css'],
    encapsulation: ViewEncapsulation.None
})

export class AppComponent implements AfterViewInit {	
	@ViewChild("grid", { read: GridComponent, static: false }) grid: GridComponent;

    // setup Datagrid's price column template.
    changeTemplate(formatObject: any) {
        const value: number = formatObject.value, opacity: number = Math.abs(value) / 100;
        if (value < 0) {
            formatObject.cell.background = `rgba(229, 57, 53, ${opacity})`;
        }
        else if (value > 0) {
            formatObject.cell.background = `rgba(67, 160, 71, ${opacity})`;
        }
        formatObject.template = value + '%';
    }
	
	// setup Datagrid appearance.
	appearance = {
        alternationCount: 2,
        showColumnLines: false,
        showColumnHeaderLines: false
    };
	
	// setup Datagrid columns resize.
    behavior = { columnResizeMode: 'growAndShrink' };
  
    // setup Datagrid data source.  
    dataSource = new window.Smart.DataAdapter({
        dataSource: [],
        dataFields: [
            'commodity: string',
            'price: number',
            'priceChange: number',
            'day: number',
            'week: number',
            'month: number',
            'year: number',
            'date: date'
        ]
    });
	
	// setup Datagrid columns.
    columns = [
        { label: 'Commodity', dataField: 'commodity' },
        {
            label: 'Price', dataField: 'price', align: 'left', cellsAlign: 'left', template: function (formatObject: any) {
                const value: number = formatObject.value.toFixed(2);
				const priceChange: number = (this as any).grid.dataSource[formatObject.row.index].priceChange;
              
  			    if (priceChange === 0) {
                    formatObject.template = value;
                }
                else {
                    formatObject.template = `
${priceChange}
${value}`;
                }
            }
        },
        { label: 'Weekly', dataField: 'week', template: this.changeTemplate },
        { label: 'Monthly', dataField: 'month', template: this.changeTemplate },
        { label: 'Yearly', dataField: 'year', template: this.changeTemplate }
    ];
			
    ngAfterViewInit(): void {	
		const that = this;
		
		// init demo server.
		const demoServer = this.setupDemoServer(),
		initServer = demoServer.init(),
		serverData = demoServer.getData();
	  	initServer.subscribe(function(dataRows) {
		
		that.dataSource = new window.Smart.DataAdapter({
				dataSource: dataRows.slice(0),
				dataFields: [
					'commodity: string',
					'price: number',
					'priceChange: number',
					'day: number',
					'week: number',
					'month: number',
					'year: number',
					'date: date'
				]
			});
		 
		serverData.subscribe(function(rows) {
				// suspend updates.
				that.grid.beginUpdate();
				
				// update cell values. 
				for(let i = 0; i < that.grid.rows.length; i++) {
					const row = that.grid.rows[i];
					const priceCell = row.getCell('price');
					const priceCellChange = row.getCell('priceChange');
				
					row.data.priceChange = rows[i].priceChange;
					row.data.price = rows[i].price;				
				}
				
				// resume updates.
				that.grid.endUpdate();
		  });
		});
    }
	
	// setup demo server.
	setupDemoServer() {
	  function demoServer() {
		'use strict';
		this.dataRows = [];
	  }
	  
	  // init server and fetch data from url.
	  demoServer.prototype.init = function() {
		return from(
		  new Promise((resolve, reject) => {
			  fetch('https://raw.githubusercontent.com/HTMLElements/smart-webcomponents-angular/master/data.json')
			  .then(response => response.json())
			  .then(data => {
					let dataSet = data;
					this.dataRows = dataSet.map((value) => {
						const newData = Object.assign(value);
						newData.priceChange = 0;
						
						return newData;
					});
					
					resolve(this.dataRows);
			  });
		  })
		);
	  };

      // get data and update it every 1s using Observable.
	  demoServer.prototype.getData = function() {
		const that = Object(this);
		
		// dynamic updates.
		return Observable.create(function(observer) {
		  const interval = setInterval(() =>{
			for (let i = 0; i < that.dataRows.length; i++) {
			    const index = Math.floor(that.dataRows.length * Math.random());
				const currentdataRows = that.dataRows[index];
				let value = currentdataRows.price;
				
				if (Math.random() > 3 / 5) {
					value = value + 1e-10;
					currentdataRows.priceChange = 0;
					continue;
				}

				let valueChange = (Math.random() > 0.5 ? 1 : -1) * value * ((Math.random() * 15 + 1) / 100);

				valueChange = parseFloat(valueChange.toFixed(2));

				value = Math.max(1, parseFloat((value + valueChange).toFixed(2)));
				currentdataRows.price = value;
				currentdataRows.priceChange = valueChange;
			}
			
			observer.next(that.dataRows);
		  }, 1000);
		  return function() {
			window.clearInterval(interval);
		  };
		});
	  };


	  return new demoServer();
	}
}



Full tutorial: https://www.htmlelements.com/docs/angular-rxjs/

This entry was posted in Angular, Smart Grid, Web Components. Bookmark the permalink.

Leave a Reply