I am following Sail.js tutorial from http://irlnathan.github.io/sailscasts/blog/2013/08/27/building-a-sails-application-ep4-handling-validation-errors-with-a-flash-message/<
In a normal mvc like rails or cakephp handling flash is something like this: $this->Flash->error('An Error Occurred Message'); then displayed it in an element.
In sails it should be simple as that.
In Controller: req.flash('error', 'An Error Occurred Message');
In View Partial: flash.ejs
<% if (req.session.flash) { %>
<% if (req.session.flash.success) { %>
<div data-alert class="alert-box success radius">
<%= req.flash('success') %>
<a href="#" class="close">×</a>
</div>
<% } %>
<% if (req.session.flash.warning) { %>
<div data-alert class="alert-box warning radius">
<%= req.flash('warning') %>
<a href="#" class="close">×</a>
</div>
<% } %>
<% if (req.session.flash.error) { %>
<div data-alert class="alert-box alert round">
<%= req.flash('error') %>
<a href="#" class="close">×</a>
</div>
<% } %>
<% } %>
On Layout:
<%- partial('partials/flash') %>
Handling Error Message per field should be part in a Validation and Html Helper. (Like for example: https://gist.github.com/mikermcneil/8366092)
You can add this export:
module.exports = function flash(req, res, next) {
if (!req.session.flash) {
req.session.flash = {};
req.session.flash['success'] = [];
req.session.flash['warning'] = [];
}
next();
};
and then in the view:
<% if (req.session.flash['success'].length > 0) { %>
<div class="alert alert-success">
<%= req.session.flash['success'].pop() %>
</div>
<% } %>
<% if (req.session.flash['warning'].length > 0) { %>
<div class="alert alert-warning">
<%= req.session.flash['warning'].pop() %>
</div>
<% } %>
You can create messages in the controller like this:
req.session.flash['success'].push('Updated successfully');
EDIT: See the Sails documentation here for more information - basically, since you're using static routing, no policies are applied before rendering the view, hence the flash policy isn't working. I'd recommend adding a register
action in your UserController
and just calling res.view()
from there. There's also a StackOverflow post that discusses this, if you want more information.
I do have an alternative I developed for my own project that you can try out (also requires non-static routing).
In your api/policies
folder, create a policy flash.js
:
// flash.js policy
module.exports = function(req, res, next) {
res.locals.messages = { success: [], error: [], warning: [] };
if(!req.session.messages) {
req.session.messages = { success: [], error: [], warning: [] };
return next();
}
res.locals.messages = _.clone(req.session.messages);
// Clear flash
req.session.messages = { success: [], error: [], warning: [] };
return next();
};
This policy allows for three different flash types: success, warning, and error. It'll create an empty dictionary for each session and clear it on page loads.
I created a service FlashService.js
in api/services
to more easily flash messages:
// FlashService.js
module.exports = {
success: function(req, message) {
req.session.messages['success'].push(message);
},
warning: function(req, message) {
req.session.messages['warning'].push(message);
},
error: function(req, message) {
req.session.messages['error'].push(message);
}
}
Then, in your config/policies.js
config file, make sure to assign the flash
policy to the controller actions that you want to use flash with:
// config/policies.js
module.exports.policies = {
'*': [true, 'flash'],
'UserController': {
'register': ['flash'],
// any future actions that want flash
},
'AnotherController': {
'someAction': ['flash', 'somePolicy'],
}
}
To flash a message in your register
action, just use FlashService.success(req, message)
. Alternatively, you can use FlashService.error
and FlashService.warning
, depending on how your UI styling works and how much you want to differentiate your flash messages.
In your view, you can put something like this:
<% if (messages && messages['error'].length > 0) { %>
<div class="alert alert-danger">
<% messages['error'].forEach(function(message) { %>
<%= message %>
<br>
<% }); %>
</div>
<br>
<% } %>
<% if (messages && messages['warning'].length > 0) { %>
<div class="alert alert-warning">
<% messages['warning'].forEach(function(message) { %>
<%= message %>
<br>
<% }); %>
</div>
<br>
<% } %>
<% if (messages && messages['success'].length > 0) { %>
<div class="alert alert-success">
<% messages['success'].forEach(function(message) { %>
<%= message %>
<br>
<% }); %>
</div>
<br>
<% } %>
Of course, you'll have to change the div
classes to whatever classes are relevant to your UI.