I've been playing around with Sails for maybe one day. I'm trying to wrap my head around what would be the best way to do extensive validation in Sails.js.
Here is the scenario:
Registration Form:
Username: _______________
E-Mail: _______________
Password: _______________
Confirm: _______________
User inputs:
Desired outcome:
Username: _______________ x Already taken
E-Mail: _______________ ✓
Password: _______________ ✓
Confirm: _______________ x Does not match
Requirements, a few key points:
What I think I need to do:
UserController:
create: function(req, res) {
try {
// use a UserManager-Service to keep the controller nice and thin
UserManager.create(req.params.all(), function(user) {
res.send(user.toJSON());
});
}
catch (e) {
res.send(e);
}
}
UserManager:
create: function(input, cb) {
UserValidator.validate(input); // this can throw a ValidationException which will then be handled by the controller
User.create(input, cb); // this line should only be reached if the UserValidator did not throw an exception
}
User: (model)
attributes: {
username: {
type: 'string',
required: true,
minLength: 3,
unique: true
},
email: {
type: 'email',
required: true,
unique: true
},
password: {
type: 'string',
required: true
}
}
UserValidator:
This is the tricky part. I need to combine input-specific validation (does the password confirmation match?) with the Model validation (is the username taken and is the e-mail address valid?).
If there was a way to instantiate a User-model and perform validation without saving to the database in Sails/Waterline I think this would be quite straight-forward, but there doesn't seem to be that option.
How would you go about solving this problem? Thank you very much for your help!
Steps to use express-validator to implement the logic:Install express-validator middleware. Create a validator. js file to code all the validation logic. Validate confirmPassword by validateConfirmPassword: check('confirmPassword') and chain on all the validation with ' .
It checks that the password entered by the user is same as this confirm password fields. To create a valid password, both the password and confirm password fields value must be matched. First one, we will check for a valid password and then confirm password validation checks.
should be javascript:validate(...) or just validate(...) . Use <script type="text/javascript"> to start a (java)script element. You need to wrap string values in quotes (i.e. workshop should be "workshop" ). Change name="text1" to id="text1" and then you can get the value using document.
Sails. js uses Grunt as a build tool for building front-end assets. If you're building an app for the browser, you're in luck. Sails ships with Grunt — which means your entire front-end asset workflow is completely customizable, and comes with support for all of the great Grunt modules which are already out there.
You can do this in your model:
module.exports = {
types: {
mycustomtype: function (password) {
return password === this.confirm;
}
},
attributes: {,
password:{
type: 'STRING',
required: true,
mycustomtype: true
}
}
}
There are going to be some validations that you can perform immediately on the client-side without needing to round-trip to the server. Things like comparing the password with the confirmation password, as well as verifying a string matches an email regex can be done with client-side javascript.
For other things like checking whether a username exists or not, you could use an ajax call to sails to directly ask it 'does this username exist' and provide real-time validation on the client-side based on the result, or you can wait until the user submits the form and parse the form submission to display those validations. Since checking ahead of time for things like this aren't 100% reliable (i.e. someone could create a user with that name after the check but prior to the form being posted back), some people choose to forgo the pre-check and only handle the error after post.
Waterline has its own built-in validation mechanism called Anchor, which is built on validator.js (previously called node-validator). For a full list of validations available, see here. I would recommend that instead of defining a separate validation layer, you define a method that parses the sails validation messages and formats them in a way that is user-friendly and consistent.
If you want to perform your own validations outside of what Waterline would do for you, you could do those validations inside a lifecycle callback, for instance the beforeCreate(values, callback)
lifecycle callback. If you detect errors, you could pass them into the callback as the first parameter, and they would be passed back as an error to the caller of the create collection method.
An alternative to using a lifecycle callback, would be to create your own collection method that handles the create. Something like this:
Users.validateAndCreate(req.params.all(), function (err, user) {
...
});
More information about how to create a collection method like this can be found in my answer to this question: How can I write sails function on to use in Controller?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With