These instructions will take you through the process of creating your first forms-angular application, which will consist of an input form for a simple model, a listing showing data already on file, search, menus and a simple report with several features including outputting to PDF.
If you want a sneak preview of what the input form will look like when you have finished take a look at one of the examples - there is a simple input form here and a more feature-filled one here.
(if you need to - you may already have these applications / packages installed)
Please note: the "just a few minutes" in the title starts from after these are installed!
npm install -g express
npm install -g bower
You have the option at this point (if you are really lazy and you
aren't worried about stuff happening in scripts you have never seen) you
can do wget https://raw.github.com/mchapman/forms-angular/master/app/partials/get-started/get-started.sh && bash get-started.sh.
If you want to understand a bit more about how the example app works you
are better off working through the instructions below.
Several other packages / components are installed by npm / bower, and some of them need to be understood before you can make best use of forms-angular (though you can do simple forms without). forms-angular is based on what has become known as the MEAN stack - made up of Mongo, Express and Node (all installed above) and Angular JS. All of these come with extensive documentation on their websites.
In addition to the MEAN stack, some grasp of Mongoose is a good idea for all but the simplest of forms, and knowledge of Twitter Bootstrap is recommended.#!/bin/sh
mkdir myapp
cd myapp
express
npm install
if [ $1 ]; then
npm install forms-angular-test --save
else
npm install forms-angular --save
fi
npm install mongoose --save
cd public
if [ $1 ]; then
bower install forms-angular#dev --allow-root
else
bower install forms-angular --allow-root
fi
cd ..
var mongoose = require('mongoose');
var formsAngular = require('forms-angular');
mongoose.connect('mongodb://localhost/mydb');
var Schema = mongoose.Schema;
var ApplicantSchema = new Schema({
surname: {type:String, required:true, index:true},
forename: {type:String, index:true}
});
var Applicant = mongoose.model('Applicant', ApplicantSchema);
var DataFormHandler = new (formsAngular)(app);
DataFormHandler.addResource('applicant', Applicant); // Create and add more schemas to taste
and comment out any lines that start with app.get(:
// app.get('/', routes.index);
// app.get('/users', user.list);
Create the following files:
public/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My App</title>
<base href="/">
<script type="text/javascript" src="/bower_components/jquery/jquery.js"></script>
<script type="text/javascript" src="/bower_components/jquery-ui/ui/jquery-ui.js"></script>
<link rel="stylesheet" href="/bower_components/jquery-ui/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="/bower_components/angular/angular.js"></script>
<script type="text/javascript" src="/bower_components/angular-route/angular-route.js"></script>
<script type="text/javascript" src="/bower_components/angular-sanitize/angular-sanitize.js"></script>
<script type="text/javascript" src="/bower_components/underscore/underscore.js"></script>
<script type="text/javascript" src="/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.js"></script>
<script type="text/javascript" src="/bower_components/angular-ui-date/src/date.js"></script>
<script type="text/javascript" src="/bower_components/angular-ui-select2/src/select2.js"></script>
<script type="text/javascript" src="/bower_components/ngInfiniteScroll/build/ng-infinite-scroll.js"></script>
<script type="text/javascript" src="/bower_components/jspdf/dist/jspdf.debug.js"></script>
<script type="text/javascript" src="/bower_components/bootstrap/js/bootstrap-transition.js"></script>
<script type="text/javascript" src="/bower_components/bootstrap/js/bootstrap-collapse.js"></script>
<link rel="stylesheet" href="/bower_components/ng-grid/ng-grid.css">
<script type="text/javascript" src="/bower_components/ng-grid/ng-grid-2.0.7.debug.js"></script>
<link rel="stylesheet" href="/bower_components/select2/select2.css">
<script type="text/javascript" src="/bower_components/angular-elastic/elastic.js"></script>
<script type="text/javascript" src="/bower_components/select2/select2.js"></script>
<script type="text/javascript" src="/bower_components/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="/bower_components/ng-ckeditor/ng-ckeditor.js"></script>
<!--[if lt IE 9]>
<script src="/bower_components/html5shiv-dist/html5shiv.js"></script>
<![endif]-->
<!--forms-angular stuff-->
<link rel="stylesheet" href="/bower_components/forms-angular/css/forms-angular-bs2.css">
<script type="text/javascript" src="/bower_components/forms-angular/forms-angular.js"></script>
<script src="/myapp.js"></script>
<style type="text/css" media="all">
.brandpluslogo {
font-size: x-large;
font-weight: bold;
}
</style>
</head>
<!--The NavCtrl controller is responsible for parsing the URL and loading the menu for the model and form-->
<body ng-app="myApp" ng-controller="NavCtrl" ng-keyup="globalShortcuts($event)">
<div class="navbar navbar-default navbar-fixed-top">
<div class="navbar-inner">
<div class="container-fluid" ng-cloak>
<button type="button" class="navbar-toggle btn btn-navbar" data-toggle="collapse" data-target=".navbar-collapse">
<span class="glyphicon glyphicon-bar icon-bar"></span>
<span class="glyphicon glyphicon-bar icon-bar"></span>
<span class="glyphicon glyphicon-bar icon-bar"></span>
</button>
<div class="pull-left">
<a class="navbar-brandpluslogo brandpluslogo" ng-href="{{buildUrl('index')}}">Demo</a>
</div>
<div class="visible-lg visible-desktop pull-right col-md-2 span2"></div> <!-- Leave some space for github flash -->
<global-search class="global-search"></global-search>
<div class="navbar-collapse collapse nav-collapse">
<ul class="nav navbar-nav">
<li ng-show="items.length > 0" class="dropdown">
<a class="dropdown-toggle">
{{contextMenu}}
</a>
<ul class="dropdown-menu">
<li ng-repeat="choice in items">
<a class="dropdown-option" ng-hide="isHidden($index)" ng-href="{{choice.url}}" ng-click="doClick($index)">{{choice.text}}</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div ng-view></div>
</body>
</html>
public/myapp.js
var myApp = angular.module('myApp', ['formsAngular']);
myApp.config(['formRoutesProvider', function (formRoutes) {
formRoutes.setRoutes([
{route:'/index', options:{templateUrl: 'partials/index.html'}},
// The next block shows how to use custom forms for a given model rather than the generic form provided
{route:'/z_custom_form/new', options:{templateUrl: 'partials/custom-new.html'}}, // example view override
{route:'/z_custom_form/:id/edit', options:{templateUrl: 'partials/custom-edit.html'}}, // example view override
{route:'/z_custom_form/:form/new', options:{templateUrl: 'partials/custom-new.html'}}, // example view override with specified form content
{route:'/z_custom_form/:form/:id/edit', options:{templateUrl: 'partials/custom-edit.html'}} // example view override with specified form content
], '/index');
}]);
//To use one of the $locationProvider options use the call below:
//formsAngular.config(['urlServiceProvider',function(urlService) {
// urlService.setOptions({html5Mode: false, hashPrefix: '!'});
//}]);
//uncomment to use Bootstrap 3-- formsAngular.config(['cssFrameworkServiceProvider',function(cssFrameworkService) {
//uncomment to use Bootstrap 3-- cssFrameworkService.setOptions({framework:'bs3'});
//uncomment to use Bootstrap 3--}]);
public/partials/index.html
<h1>Applicants</h1>
<ul>
<li>Create a new applicant at <code><a href="/#/applicant/new">/#/applicant/new</a></code></li>
<li>List applicants at <code><a href="/#/applicant">/#/applicant</a></code></li>
<li>Edit existing applicants by clicking on the links in the <a href="/#/applicant">list</a></li>
<li>Show applicants in a <a href="/#/analyse/applicant">grid report</a></li>
</ul>
public/partials/base-edit.html
<div ng-controller="BaseCtrl">
<!--This is the header section-->
<div ng-class="css('rowFluid')" class="page-header edit-header">
<!--The left hand side contains important fields from the data-->
<div class="header-lhs col-sm-8 span8">
<h4>{{modelNameDisplay}} :
<span ng-repeat="field in listSchema">{{getListData(record, field.name)}} </span>
</h4>
</div>
<!--The right hand side contains buttons to Save, Cancel, Delete and create New-->
<div class="header-rhs col-sm-2 span2">
<div form-buttons></div>
</div>
</div>
<div class="container-fluid page-body edit-body">
<!--This section only appears when there is an error message to display-->
<div id="display-error" ng-show="errorMessage" ng-class="css('rowFluid')">
<div class="alert alert-error col-lg-offset-3 offset3 col-sm-6 span6 alert-warning alert-dismissable">
<button type="button" class="close" ng-click="dismissError()">×</button>
<h4>{{alertTitle}}</h4>
<div ng-bind-html="errorMessage"></div>
</div>
</div>
<form-input name="baseForm" schema="baseSchema()" formstyle="compact"></form-input>
</div>
</div>
public/partials/base-list.html
<div ng-controller="BaseCtrl">
<div ng-class="css('rowFluid')" class="page-header list-header">
<div class="header-lhs col-sm-8 span8">
<h1>{{modelNameDisplay}}</h1>
</div>
<div class="header-rhs col-sm-2 span2">
<button class="btn btn-default" ng-click="new()"><i class="icon-plus"></i> New</button>
</div>
</div>
<div class="page-body list-body">
<div ng-show="errorMessage" ng-class="css('rowFluid')">
<div class="alert alert-error col-lg-offset-3 offset3 col-xs-6 span6 alert-warning alert-dismissable">
<button type="button" class="close" ng-click="dismissError()">×</button>
<h4>{{alertTitle}}</h4>
<div ng-bind-html="errorMessage"></div>
</div>
</div>
<div ng-class="css('rowFluid')" infinite-scroll="scrollTheList()">
<a ng-repeat="record in recordList" ng-href="{{generateEditUrl(record)}}">
<div class="list-item">
<div ng-class="css('span',12/listSchema.length)" ng-repeat="field in listSchema">{{getListData(record, field.name)}} </div>
</div>
</a>
</div>
</div>
</div>
public/partials/base-analysis.html
<div ng-controller="AnalysisCtrl">
<div class="container-fluid page-header report-header">
<div class="row-fluid">
<div class="header-lhs span7">
<h1>{{ reportSchema.title }}</h1>
</div>
<div class="header-rhs span4">
<form-input schema="paramSchema" name="paramForm" ng-show="paramSchema" formstyle="horizontalCompact"></form-input>
</div>
</div>
</div>
<div class="container-fluid page-body report-body">
<div ng-show="errorMessage" class="row-fluid">
<div class="span6 offset3 alert alert-error">
<button type="button" class="close" ng-click="dismissError()">×</button>
<h4>{{alertTitle}}</h4>
<div ng-bind-html="errorMessage"></div>
</div>
</div>
<div class="row-fluid">
<div class="gridStyle" ng-grid="gridOptions"></div>
</div>
</div>
</div>
node app.js
Visit http://0.0.0.0:3000 in
your browser.