dandean / express-form Goto Github PK
View Code? Open in Web Editor NEWForm validation and data filtering for Express
Home Page: http://dandean.github.com/express-form
License: MIT License
Form validation and data filtering for Express
Home Page: http://dandean.github.com/express-form
License: MIT License
Reported by @shamod in the comments for this issue: #4
Here are his notes:
run into this error. i have:
input(id="name", name="user[name]", type="text", value='')
and it fails on filter
form( filter( "user[name]" ).trim( ) )
with this error
TypeError: Cannot call method 'replace' of undefined
Using v0.5.3. Any idea?
I'm pretty new to Node and I'm not sure if it is me or a limitation of Express-Form, so bear with me please;
I want to use Express-Form to validate different form submissions, but instead of adding the logic directly in the PUT/POST Request, I would like to modularize it all.
app.js contains my routes like so:
var routes_users = require('./routes/users');
app.put('/users/create', routes_users.createUser);
And I would like to call Express-Form like so:
var formValidator = require('./formValidator');
app.put('/users/create', formValidator.validate('createUser'), routes_users.createUser);
formValidator.js:
var form = require('express-form'),
filter = form.filter,
validate = form.validate;
function createUser(req, res, next) {
return form(
validate('username').required();
...
}
module.exports.validate = function(formName) {
// If anyone has a way to get rid of this switch, and directly call the function from the string, please tell me!
switch(formName) {
case "userCreate":
return createUser;
break;
}
};
So, am I doing it wrong or is this a limitation of Express-Form and it cannot be used like so?
Following the method from the examples works fine.
Thanks
How should I repopulate form fields with the submitted values?
I have a get and a post route. If there are validation errors when the form is posted, I redirect the user back to the get, the problem is that the repopulated locals don't show up (I do have autoLocals: true, so I assume it's because I am redirecting and res is reset.)
So how do you guys repopulate and what's your application flow, do you res.send instead of res.redirect and set up the whole thing again? That seems repetitive.
Here's an example of my post route:
app.post(
'/projects/:id'
, form(field("title").required("title", "Title is required)
, function (req, res){
if (!req.form.isValid){
res.redirect('/project/'+req.params.id+'/edit');
}
else{
// save to db
}
});
Have methods to deal with arrays themselves. eg/ arrayLength(), push(), etc.
Validator.prototype.required = function(placeholderValue, message) { this.__required = true; return this.add(function(value) { if (!hasValue(value) || value == placeholderValue) { throw new Error(message || "%s is required"); } }); };
But in your documentation it states that the message is the first argument and there is no second. BTW, great job, this is making life easier :)
Also through email checks, iz would be a way better choice for a library, however validator has good XSS filtering.
If a blank field is sent from the browser as "fieldname=" then trim() works on it, but if the field is omitted altogether then node returns a 500 error.
Add functionality to deviate from current configuration for a single instance.
Possible API:
form(
{
autoTrim: false,
passThrough: true
},
field("whatever").toUpper()
)
Any clue why?
When using the validate() function, node is throwing an error:
node.js:63
throw e;
^
WideCharToMultiByte: The data area passed to a system call is too small.
TypeError: undefined is not a function
at CALL_NON_FUNCTION (native)
at Object. (/mnt/e/Dev/sandbox/node.js/webdownloader/test_validate.js:21:5)
at Module._compile (node.js:462:23)
at Module._loadScriptSync (node.js:469:10)
at Module.loadSync (node.js:338:12)
at Object.runMain (node.js:522:24)
at Array. (node.js:756:12)
at EventEmitter._tickCallback (node.js:55:22)
at node.js:773:9
My code:
server.post('/',
form(
validate("download").required(),
validate("email").required()
),
function(request, response) {
....
//app.js//
var form = require("express-form"),
field = form.field,
validate = form.validate;
//express server init here//
app.all('/test',
form(
field('foo').required("this message is ignored").isAlphanumeric('this message appears'),
field('bar').required("this message is ignored too"),
validate("baz").required('just like this one...')
),
function (req, res) {
res.send(req.form.errors);
// below is what I get on GET https://mysite.org/test
// => ["foo is required","this message appears","bar is required","baz is required"]
}
);
My local npm modules are:
[email protected]
├─┬ [email protected] extraneous
│ └── [email protected]
├─┬ [email protected] extraneous
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├─┬ [email protected] extraneous
│ ├── [email protected]
│ └── [email protected]
├── [email protected] extraneous
├─┬ [email protected]
│ ├── [email protected]
│ └── [email protected]
├── [email protected] extraneous
├─┬ [email protected] extraneous
│ ├── [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ └── [email protected]
└── [email protected] extraneous
Upd: .required([message]) is actually .required([placeholderValue, message])
https://github.com/dandean/express-form/blob/master/lib/field.js#L328-336
Trying to use form(..), form(..)
in middleware throws an error because defineProperties
in form.js
tries to redefine what already exists.
Probably just need to wrap it in an if statement to check if req.form
already has those properties defined.
Hello again,
I have the same form as previously mentioned (has a due date applicable check mark and upon clicking it, a text field appears for said date). Unless I perform an empty filter() on the hidden field, it won't get passed onto the next middleware (previously this was working by doing a custom filter on the checkmark.), see code below:
Form:
<dl>
<label for="deadline">
Does your project have a planned deadline?</label>
<dd class="deadline">
<input type="checkbox" id="deadline" name="message[deadline][applicable]" value="1" />
<dt class="deadline_date">
Please enter your project’s deadline
</dt>
<input type="text" id="deadline_date" name="message[deadline][deadline]"
placeholder="Project deadline" /></dd>
And in my form route middleware, I have
field("message.deadline.applicable")
.custom(function (value, data) {
if (value && !data.message.deadline.deadline.trim()) {
throw new Error("A date must be specified if a deadline applies.");
}
}),
Now, if I leave it there, it used to still pass data.message.deadline.deadline
to the next route but now it doesn't. However, if I add this meaningless filter:
` field("message.deadline.deadline"),
then all is good again in the land of Akiva.
I can apply this now to get things working, but perhaps it is a bug?
In the runStack function, there's the following line:
// If this field is not required and it doesn't have a value, ignore error.
if (!utils.hasValue(value) && !self.__required) return;
Isn't this up to the custom function to determine if the value is required or not and when it is, it has to check for the 'requiredness' itself? Thoughts?
If you npm install express-forms it currently doesn't work because the version of validator it expects (1.2.1) is much different from the current version of validator (3.22.1).
The package.json of express-forms should be changed from:
"validator": ">= 0.1.2"
to be:
"validator": "= 0.1.2"
Hello, great plugin. I just have an issue.
if I have a field name such as
account[owner][email]
I get the following error
500 TypeError: Cannot call method 'replace' of undefined
at [object Object].trim (/usr/local/lib/node/.npm/validator/0.1.7/package/lib/filter.js:47:26)
at /usr/local/lib/node/.npm/express-form/0.5.1/package/lib/filter.js:29:36
at /usr/local/lib/node/.npm/express-form/0.5.1/package/lib/filter.js:15:29
at Array.forEach (native)
at Filter.run (/usr/local/lib/node/.npm/express-form/0.5.1/package/lib/filter.js:14:11)
at /usr/local/lib/node/.npm/express-form/0.5.1/package/lib/form.js:97:28
at Array.forEach (native)
at Object. (/usr/local/lib/node/.npm/express-form/0.5.1/package/lib/form.js:96:14)
at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)
at pass (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:162:10)
The error is due to the fact that in line 15 of filter.js you have
formData[fieldname] = filter(formData[fieldname])
So in this case formData[fieldname] becomes
formData[account[owner][email]]
wich in fact does not exist. The correct form should be
formData[account][owner][email]
So somehow your function should be able to parse field names of the form "object[field]"
Thanks for the great work.
I receive the following error:
TypeError: Object # has no method 'local'
at /Users/mwawrusch/Documents/scottyapp-project/scotty-io/node_modules/express-form/lib/form.js:32:15
which is because in express 3.0 res.locals is defined as a function, but res.local does not exist. See here: https://github.com/visionmedia/express/blob/master/lib/utils.js#L18
One way to fix it seems to check for the existence of res.local, although this is not a perfect solution.
Using Mongoose as the back-end of my forms requires field names like 'user[username]', and they're not working with express-form filters.
My forms using HTML5 form elements, which are not being parsed properly. For instance:
Won't work. However, if I change type="email" to type="text", everything works as expected.
This seems really odd, as you would think it would work fine. I heavily use HTML5 forms all the time.
Hi Dan
First of all - thanks for a great tool!
If there is any way to perform custom validation using asynchronous callbacks?
Let's say I want to validate email/username uniqueness:
.custom(function(email) {
User.find({}, function(err, user) {
throw new Error("asynchronous validation failed");
};
}
This would generate an error:
node.js:116
throw e; // process.nextTick error, or 'error' event on first tick
Error: asynchronous validation failed
at /home/nikita/Sites/nodejs/kg-uploader/controllers/users.js:47:34
at /home/nikita/Sites/nodejs/kg-uploader/lib/mongoose/lib/mongoose/query.js:573:22
at model.<anonymous> (/home/nikita/Sites/nodejs/kg-uploader/lib/mongoose/lib/mongoose/document.js:141:5)
at model.init (/home/nikita/Sites/nodejs/kg-uploader/lib/mongoose/lib/mongoose/document.js:571:33)
at /home/nikita/Sites/nodejs/kg-uploader/lib/mongoose/lib/mongoose/query.js:571:16
at /home/nikita/Sites/nodejs/kg-uploader/lib/mongoose/support/node-mongodb-native/lib/mongodb/cursor.js:122:15
at /home/nikita/Sites/nodejs/kg-uploader/lib/mongoose/support/node-mongodb-native/lib/mongodb/cursor.js:163:11
at /home/nikita/Sites/nodejs/kg-uploader/lib/mongoose/support/node-mongodb-native/lib/mongodb/cursor.js:454:28
at [object Object].close (/home/nikita/Sites/nodejs/kg-uploader/lib/mongoose/support/node-mongodb-native/lib/mongodb/cursor.js:605:17)
at [object Object].nextObject (/home/nikita/Sites/nodejs/kg-uploader/lib/mongoose/support/node-mongodb-native/lib/mongodb/cursor.js:454:10)
It looks like a common use case and many users may eventually face this problem
If there is any way to overcome it?
I used configuration as follows:
var form = require('express-form').configure({
autoTrim: true,
passThrough: true,
autoLocals: false,
dataSources: ['body']
});
and rules as follows:
form(
filter('url').trim(),
validate('url', 'URL').required()
)
I'm expecting data will be trimmed first and then the trimmed data will be validated.
When I input spaced string only (ex: ' ' ), it won't goes error (should be error because it is empty string)
I check the code and found at lib/field.js line 35
property = property.replace(/\[((.)*?)\]/g, ".$1"); // Convert square-bracket to dot notation.
var value = utils.getProp(property, form) || utils.getProp(property, source);
the value to evaluated gotten from "form" (which is the right ones) or if it is empty gotten from "source" (its bad cause, trim will make valid input empty string but you take the original from source to evaluate.
My workaround is:
property = property.replace(/\[((.)*?)\]/g, ".$1"); // Convert square-bracket to dot notation.
// REMARK by reekoheek: I disabled utils.getProp(property, source)
// and leave it to 'form' alone to validate
// as I use configuration "passThrough = true"
// var value = utils.getProp(property, form) || utils.getProp(property, source);
var value = utils.getProp(property, form); // || utils.getProp(property, source);
I hope it will help you, because it takes me hours to search documentations but cannot found about it :)
It's a bit clunky to check whether the form is valid atm, as you do it outside of the form middleware:
app.post(
"some/route",
form(
field("user.password").required()
),
function (req, res) {
if (!req.form.isValid) return res.send({ errors: req.form.getErrors() });
// Some logic here...
}
);
At the moment I'm doing this in my express app:
exports.validate = function (req, res, next) {
form(
field("user.password").required()
)(req, res, function () {
if (req.form.isValid) return next();
res.send({ errors: req.form.getErrors() });
});
};
app.post("some/route", foo.validate, foo.create);
app.post("other/route", foo.validate, foo.update);
This means I don't have to put form logic in my create/update middleware, and I don't have to repeat the error-response in each middleware. I think it would be nice to have a pre-packaged way to bundle the response in the form middleware.
it would be nice to have a config option that just auto trims everything without having to call trim on every value.
Error in form.js at 46
TypeError: Cannot set property 'field_name' of undefined
It looks "res.options" propterty is undefiend.
update:
I forgot to write software version.
[email protected]
[email protected]
express-form@github-master
have you found a maintainer yet?
It would be nice to have this:
app.configure("production", function() {
form.set("autoTrim", true);
});
I am having a difficult time trying to use the custom() method in conjunction with referring to another field outside of the one that I am calling custom() on. Perhaps you can help clarify?
ie.
validate("deadline.date").custom(function (value) { if (deadline.applicable) { ... } })
this is a really elegant solution to form validation.
another killer feature would be some way of passing the same validation logic to the browser to perform clientside validation as well as serverside.
i'm aware of browserify but not sure how this would fit in with the connect model, would need some kind of abstraction
For changes made here: #14
Line 254 in 602899b
It seems that isFloat
should have a valid response if the value is a numeric non-integer. For example: 4.5.
Perhaps the isFloat
and isDecimal
methods should be renamed to isInt
.
If you'd like, I can propose a solution and submit a PR, but I'd like to know your thoughts about this.
Thank you.
Allow to change all the default messages to other language by given lang object.
I thought I had a test for this but guess not, nested properties no longer work with equals after the recent rewrite:
e.g.
form(
form.validate('verify_password','Verify Password').equals('field::user[password]', "Passwords do not match")
)
The documentation or functionality for usage of required()
is a bit confusing.
If you just simply want to pass a custom required message, the only way to currently do so is:
form(
filter("name").trim()
, validate("name").required("name", "Please enter your %s, we'd love to know what it is!")
);
Might you update the docs? -- I could if you'd like :) Let me know.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.