Showing posts with label angularjs. Show all posts
Showing posts with label angularjs. Show all posts

Friday, February 24, 2017

A "Generic Component" in Angular 2

I am generally a lazy person. Especially so when it comes to writing some UI code (although I can have endless comments and critiques on someone else's UI and UX ;-)) . I find it repetitive. And any form of repetitive behaviour is ripe for automation. One such activity which I recently encountered in a project I was doing was creating forms - a lot of them - with Angular 2 front end. I remember in good old MS Access days these were just a click away - although I disliked it, this is what I did in my first paying job in summer break of my school.
I am not sure we have something equivalent here - more so when Angular is so rapidly changing and keeps breaking every other month.

However, it is rather easy to write a "generic component" that can be simply configured using a JSON and you can have a new form without writing any of the usual code. This has two main advantages: 1) You have a single place to fix when Angular changes something in its structure 2) You have a super reusable form engine which can be configured on the fly, allowing you to do cool things like storing form info in a backend service, and automatically update the Angular 2 app on the fly.

To start off, you will need to define a JSON which can be used to construct the UI on the fly.

this.componentJSON = {};
this.componentJSON['title'] = "Trials";

this.componentJSON['formItems'] = [
 { "type": "text", "id": "trial", "name": "Trial Name", "description": "Name of trial", "theValue": "", "param_name": "trial_name" },
 { "type": "text", "id": "sponsorer", "name": "Sponsorer", "description": "Sponsorer of the trial", "theValue": "", "param_name": "sponsorer_name" },
 { "type": "button", "id": "submit", "name": "Submit", "description": "Submit the form", "api_call": this.createTrial },
];


The above JSON is intended to create a simple form with a title, two text fields and a button. The api_call parameter of the button is a Service object used to make an API call.  This JSON should be used in any parent component that intends to use this component, typically being initialised in ngOnInit() method.

Next we define generic.component.ts and generic.component.html as follows

import { Component, OnInit, Input } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';

@Component({
   moduleId: module.id,
   selector: 'generic-cmp',
   templateUrl: 'generic.component.html'
})
export class GenericComponent implements OnInit {

   @Input()
   componentJSON: any;

   constructor() { }

   ngOnInit() {
   }

   callAPI(item: any) {
     item.api_call.api_call(this.processInput(this.componentJSON)).subscribe((res:any) => {      
if (res.status == 0) {
        alert(res.result.message);  
} else {
        alert(res.error.error_message);  
}
     });
   }

   processInput(componentJSON: any) {
     var formItems = componentJSON['formItems'];

     var params: any;
     params = {};
     for(var frmItm in formItems) {
if (formItems[frmItm].type != 'button') {
        params[formItems[frmItm].param_name] = formItems[frmItm].theValue;
}
     }

     return params;
   }
}













The trick as always is to generalise the JSON and then the generic component generator above to take care of different input forms as well as adding validations. The callAPI function above for instance, basically generalises an API call, where as the processInput method creates the parameter payload for API call from the JSON we created earlier. Advantage again being that simply changing the JSON pretty much re-creates the whole of the HTML. Creating a different form just requires one to define a new JSON.

Since this component needs to be used in multiple places it would be wise to declare the directives associated with this component in a shared.module.ts file:

import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { BrowserModule } from '@angular/platform-browser';

import { NameListService } from './name-list/index';
import { GenericComponent } from './generic-component/generic.component';

@NgModule({
    imports: [CommonModule, RouterModule, FormsModule],
    declarations: [GenericComponent],
    exports: [CommonModule, FormsModule, RouterModule, BrowserModule, GenericComponent],    
})

export class SharedModule {
    static forRoot(): ModuleWithProviders {
        return {
            ngModule: SharedModule,
            providers: [NameListService]
        };
    }
}


Now a third component can embed this reusable, configurable component as using:



Thats it! You should have a fairly reusable forms module, that you can fully configure using the JSON, without the need to keep writing the HTML and related Component code every time. 

A similar pattern may also be used for creating a generic service call. This is again useful as you code can remain independent of the changes that may occur in basic underlying syntax of say actually calling the HTTP post method. 

Monday, November 23, 2015

Live Molecule search: a quick hack using JSME, Cactus, AngularJS and BootStrap

For an internal project, I needed a web control that will display the structure of the molecule as I type in the name (or SMILES, CAS number, IUPAC name or a host of other ways you can textually describe a molecule in one line). Now this is not really easy, but thanks to the some open APIs provided by the CADD group at NIH/NCI (http://cactus.nci.nih.gov), it was really easy to get this done.

Here is a quick overview of the hack I wrote. The code for the same is available on GitHub (https://github.com/tovganesh/mol-auto-view.js)

The final control. You give a molecule description, the molecule appears in draw area, click "Save to list" and it gets saved to a list that is depicted on the right hand side.


The Cactus (http://cactus.nci.nih.gov/chemical/structure)

The molecule description can be given in various ways, and it usually a very tiresome task to think through and write interpreters. One can of course use tools like Open Babel or CDK, but a more cleaner interface is a web service offered by NCI, called the Cactus. A simple API call as follows,
gives you a mol file that can be viewed:

http://cactus.nci.nih.gov/chemical/structure/[Molecule Description]/pdf


JSME (http://peter-ertl.com/jsme/)

Next to view this structure, I use the simple but powerful 2D molecule drawing tool by Peter Ertl and Bruno Bienfait (http://peter-ertl.com/jsme/)

I, particularly use the following API:

jsmeApplet.reset();
jsmeApplet.readMolFile(dataFromCactusAPICall);


The above call is the clear the drawing area, and read in the new molecule file obtained from call to the Cactus API.

Next, I need to get the molecule file data from JSME and well as a graphics representation to show in a list. This is does using the following API call:

molFile: jsmeApplet.molFile(),
molImage: btoa(jsmeApplet.getMolecularAreaGraphicsString())


The first call is for getting the molecule data, as a mol file. The second call is to get the graphics of the molecule as a SVG data, that is then encoded to base64.

Putting it all together: Angular JS and Bootstrap

Putting it all together required using Angular JS and some basic Bootstrap. The following is used for the text field that takes the molecule description:



The above code is used to fetch the mol data from giving a call to the cactus API, as you type the molecule text. The model change even is delayed by 750ms, so that the API call is only fired, when the user pauses for some time. 

Thats it! I hope you find it useful. To see the full code see Github: https://github.com/tovganesh/mol-auto-view.js