UNPKG

3.36 kBJavaScriptView Raw
1/*!
2 * Express - Form
3 * Copyright(c) 2010 Dan Dean <me@dandean.com>
4 * MIT Licensed
5 */
6
7var async = require("async")
8 , utils = require("./utils")
9 , Field = require("./field");
10
11function form() {
12 var routines = Array.prototype.slice.call(arguments)
13 , options = form._options;
14
15 return function (req, res, next) {
16 var map = {}
17 , flashed = {}
18 , mergedSource = {};
19
20 if (!req.form) req.form = {};
21
22 options.dataSources.forEach(function (source) {
23 utils.merge(mergedSource, req[source]);
24 });
25
26 if (options.passThrough) req.form = utils.clone(mergedSource);
27
28 if (options.autoLocals) {
29 for (var prop in req.body) {
30 if (!req.body.hasOwnProperty(prop)) continue;
31
32 /*
33 * express 1.x and 3.x
34 * ------------------------
35 * res.locals.field = value
36 *
37 * express 2.x
38 * ------------------------
39 * res.local(field, value)
40 * res.locals({field: value});
41 */
42 if (typeof res.local === "function") {
43 // express 2.x
44 res.local(utils.camelize(prop), req.body[prop]);
45 } else {
46 // express 1.x and 3.x
47 if (!res.locals) res.locals = {};
48 res.locals[utils.camelize(prop)] = req.body[prop];
49 }
50 }
51 }
52
53 Object.defineProperties(req.form, {
54 "errors": {
55 value: [],
56 enumerable: false
57 },
58 "getErrors": {
59 value: function (name) {
60 if(!name) return map;
61
62 return map[name] || [];
63 },
64 enumerable: false
65 },
66 "isValid": {
67 get: function () {
68 return this.errors.length === 0;
69 },
70 enumerable: false
71 },
72 "flashErrors": {
73 value: function () {
74 if (typeof req.flash !== "function") return;
75 this.errors.forEach(function (error) {
76 if (flashed[error]) return;
77
78 flashed[error] = true;
79 req.flash("error", error);
80 });
81 },
82 enumerable: false
83 }
84 });
85
86 //routines.forEach(function (routine) {
87 async.each(routines, function(routine, cb) {
88 routine.run(mergedSource, req.form, options, function(err, result) {
89
90 // return early if no errors
91 if (!Array.isArray(result) || !result.length) return cb(null);
92
93 var errors = req.form.errors = req.form.errors || []
94 , name = routine.name;
95
96 map[name] = map[name] || [];
97
98 result.forEach(function (error) {
99 errors.push(error);
100 map[name].push(error);
101 });
102
103 cb(null);
104
105 });
106 }, function(err) {
107
108 if (options.flashErrors) req.form.flashErrors();
109 if (next) next();
110
111 });
112 }
113}
114
115form.field = function (property, label) {
116 return new Field(property, label);
117};
118
119form.filter = form.validate = form.field;
120
121form._options = {
122 dataSources: ["body", "query", "params"],
123 autoTrim: false,
124 autoLocals: true,
125 passThrough: false,
126 flashErrors: true
127};
128
129form.configure = function (options) {
130 for (var p in options) {
131 if (!Array.isArray(options[p]) && p === "dataSources") {
132 options[p] = [options[p]];
133 }
134 this._options[p] = options[p];
135 }
136 return this;
137}
138
139module.exports = form;
\No newline at end of file