Hi,
I used AngularJS to build a proof-of-concept ERP web application. The goal was to evaluate if it is feasible to use Angular for that kind of applications. The lessons learned might be interesting for some you, so here is the story.
By complex ERP applications I mean a huge database, lots of different entities, form based interaction with the data using typical CRUD scenarios, does not need to run at internet-scale, deployed in an Intranet.
The basic parameters for the proof-of-concept application were:
- Built on a CRM style setting
- The client uses AngularJS (1.2)
- The server provides a REST-API to the client.
- The application is multi-locale, multi-language
- The application should demonstrate different access control scenarios.
- The application is a single-page app, but allowing for an arbitrary complex client state.
Communication between server and browser consists of
- initial HTML GET requests for a login and main page
- subsequent requests for HTML templates and script files as the user interacts with the application
- subsequent JSON requests to load and save data. No dynamic data is contained in HTML pages or templates.
The interface design is as follows:
After authentication you enter the main page: The main page just shows a menu which allows you to open module panels. Modules exist for the different database entities (customer, opportunity, contact, user).
A module panel first display a search page. Selecting an entry from the search result opens a detail panel, showing the data of the selected entity in one or more form panels.
You can open an unlimited number of module panels at the same time, which are collected in a tab-set(see screenshot attachment).
The Implementation is as follows:
GUI Interaction:was strictly implemented with Angular. This is the stuff we all know and love.
Routing:Since routing does not make sense for such a user interface, it was not used at all.
However the REST API of the server allows for different entry points into the application:
GET /crm opens the main page
GET /crm/customers opens a customer module panel in an own page, no main menu shown
GET /crm/customers/search opens the customer search panel in an own page
GET /crm/customers/100 opens the detail panel of customer 100 in an own page
etc.
This is definitely great especially for development (directly open the panel you currently work on), but requires considerable flexibility of the server REST API.
Authentication:When you enter the application a login form is presented. Since the application allows to build a complex client state, you don't want to start over again when the server session has a time out, and be thrown back to the login page.
Therefore I intercepted the HTTP requests and show a login popup when a 401 response arrives, and after successful authentication resend the failed request. Works great. (Uses http interceptors, broadcasts, implemented in an own reusable angular module).
Security:Is implemented on the server, which is responsible to check if a client request to a resource is allowed. Responses (HTML pages, templates and JSON data) is tailored to the user. The client does not implement any user specific filtering. A good template and security system on the server is key.
Lazy loading:Because of potential huge application size, I don't want to load all controller scripts and HTML templates from the main page. I implemented an Angular directive and reusable module which allows to transparently load scripts and HTML templates.
(The directive internally uses script.js to load script files). When applications panels (e.g. customer search panel, customer detail panel, etc.) are opened the first time, panel content and associated scripts are silently loaded. Works great but requires good organization of the REST API and server-side implementation.
Performance:Performance of a client side ERP application might be a huge concern. I didn't experienced any slow down, but the POC implementation would need to be more detailed and complete to test the limits. Again performance improvements in Angular 2.0 may disarm the concern.
Protocol (experimental):A REST-API is typically data-centric and agnostic of the client. But it might be useful to think of the interaction of an ERP client and server not in terms of calls to a general API but more of an protocol.
Here the server knows it specific client. Its responses are not just raw data, but more like instructions.
I just came up with a simple use case:
- Client makes a server call; the returned JSON object should be put into the current angular scope.
Now we would typically pass a callback to the http promise, and in the callback put the received data into the scope.
In a protocol centric implementation the server could not just send the data, but also an instruction to put it into the scope. This instruction can be interpreted by a http response processor on the client side, and in my specific situation I wouldn't need to supply the callback.
This are just very rudimentary thoughts. Maybe this is just what Meteor does at bigger scale?
Localization:Text contained in HTML responses is localized to the user, and implemented on the server. But since an ERP app would need to respond to user interactions (e.g. displaying error messages), a client-side service to translate texts would also be needed. Did not implement this topic, but again you would need to add technical infrastructure to make this work.
Validation of user input:Angular can be used to validate user input, but of course you need to revalidate submitted JSON data on the server. Did not implement this, but of course this a big architectural point.
Common points:Organization of scripts and controller code is crucial, since I would expect lots of fine-grained script files (to enabled lazy-loading). I tried to not hardcode URLs to server-side resources in js scripts.
The announced simplification of controllers in Angular 2.0 may bring real benefits here.
Conclusion:Finally I had mixed feelings about the solution, because technical infrastructure to organize communication between Angular client and server was huge. Of course you might come up with better solutions.
Code:You can find the complete source code of the POC crm app (server and client-side) at
https://github.com/jdlib/civilian.
A short description of the POC crm app and how to run it can be found here
http://www.civilian-framework.org/doc-samples.html#crmbest,
Johannes