How to render a view into a string in SailsJS? - sails.js

In one controller I want to render a certain view with a certain layout to send an email with the resulting string, but I obviously do not need to show the result to the user. Is there a way to use the EJS engine that I'm using to render views to achieve this? Here's my a bit simplified controller action:
setEmail: function(req, res) {
var update = {
activationToken: _getToken(),
email: req.param('email')
};
Profile.update(res.locals.profile.id, update).then(function(profile) {
res.redirect(profileUrl);
mailer.sendActivationEmail(
update.email,
res.i18n('Подтвердите свой адрес электронной почты'),
emailString); // <=== Here is where I need the string rendered from a view
});
},

Use the view-hook
Profile.update(res.locals.profile.id, update).then(function(profile) {
res.redirect(profileUrl);
sails.hooks.views.render("viewname",profile, function(err,html){
if(err) return console.log(err);
mailer.sendActivationEmail(
update.email,
res.i18n('Подтвердите свой адрес электронной почты'),
html
);
})
});
Edit: right callback

I think I would rather use a specific email module like this one:
https://github.com/niftylettuce/node-email-templates
Which can access EJS templates

Related

How to seperate Vue logic in a laravel app based on layout and page templates

I have a laravel app and a Vue instance attached to the body (or a div, just inside the body).
const app = new Vue({
el: '#app'
});
I think it makes sense to use the Vue instance for stuff relating to the layout (eg header, nav, footer logic).
Now I have a form that is visible on a specific route (e.g. example.com/thing/create). I want to add some logic to it, e.g. hiding a field based on selected option in the form. It is logic meant for just this form (not to be reused). I prefer not to put all the logic inline with the form but put it in the app.js. I could put it in the Vue instance bound to the body but that sounds odd as it only applies to the form that is much deeper into the dom.
I want to leave the markup of the form in the blade template (that inherits the layout).
I tried creating a component but am not sure how to bind this inside the main Vue instance. What is the best way to handle things for this form, put it in the app.js and have it somewhat structured, putting the variables somewhat into scope. Or is it really necessary to remove the main Vue instance bound to the full layout code?
What I tried was something like this, but it does not work (attaching it to the <form id="object-form"> seems to fail:
var ObjectForm = {
template: function() { return '#object-form'},
data: function() {
return {
selectedOption: 1
}
},
computed: {
displayField: function() {
// return true or false depending on form state
return true;
}
}
};
Things do work if I remove the #app Vue instance or when I put everything directly in the app Vue instance. But that seems messy, if I have similar variables for another form they should be seperated somewhat.
I would appreciate some advice regarding the structure (differentiate page layout and page specific forms) and if possible some example to put the form logic inside the main app.js.
I hope this helps kind of break things down for you and helps you understand Vue templating.
It is best to take advantage of Vue's components. For you it would look something like this. Some of this code depends on your file structure, but you should be able to understand it.
In your app.js file (or your main js file)
Vue.component('myform',require('./components/MyForm.vue'));
const app = new Vue({
el: "#app"
});
Then create the MyForm.vue file
<template>
<form>
Put Your Form Markup Here
</form>
</template>
<script>
// Here is where you would handle the form scripts.
// Use methods, props, data to help set up your component
module.exports = {
data: function() {
return {
selectedOption: 1
}
},
computed: {
displayField: function() {
// return true or false depending on form state
return true;
}
},
methods: {
// add methods for dynamically changing form values
}
}
</script>
Then you will be able to just call in your blade file.
<myform></myform>
I found out how to do it. The trick was to use an inline template. Surround the form in the view with:
<object-form inline-template>
<form>...</form>
</object-form>
Where object-form is the name of the component. In the ObjectForm code above I remove the template, like this:
var ObjectForm = {
data: function() {
return {
selectedOption: 1
}
},
computed: {
displayField: function() {
// return true or false depending on form state
return true;
}
}
};
I attach the component within the root vue app like this:
const app = new Vue({
el: 'body',
components: {
'object-form': ObjectForm
}
});
This way I can use the form as it was generated from the controller and view and I can separate it from the root (attached to body) methods and properties.
To organize it even better I can probably store the ObjectForm in a seperate .vue file the way #Tayler Foster suggested.

Chaining Controller Actions to one Route

I'm not sure what I am doing wrong here. I'm following this example here: https://gist.github.com/mikermcneil/5737561.
I want to chain two controller actions to one 'get' route. I need to return some json data and also a view. When attempting to send the data with the view I get an socket.io error message that says I can't send information through views.
'get /users': [
{
controller: 'UserController',
action: 'users'
},
{
controller: 'UserController',
action: 'getuser'
}
],
Right now to make it work I have to have two 'get' routes. One that returns my view ejs file and another that the socket can connect too.
var socket = io.connect('http://localhost:1337');
socket.get('/user', {}, function(users) {
var grid = new Slick.Grid("#userGrid", users.users, columns, options);
});
This works but then I have a random /user route out there that anyone can access that just returns json. I'd like to not have random routes that can be accessed through the browser if possible. So can I chain controller actions to one route? Or is there a way to return a res.view and json data in one action?
users: function(req, res, next) {
//User.find().populateAll().exec(function(err, users){
res.view('user/users');
next();
// res.json({
// success: true,
// users: users
// });
//});
},
//get user data and send it as json to for sockets
getuser: function (req, res) {
User.find().populateAll().exec(function(err, users) {
res.json({users: users});
});
},
I tried using next() and without. Thanks for any help!

Extjs file upload progress

I have seen form file upload example in ExtJS4 and i need customize progress of the file upload.
I see waitMsg config property, but i don't want use that and i don't want use extjs 3rd party plugins.
So, how i can get simply current upload progress from upload form in extjs?
The waitMsg uses a message box with an infinitely auto-updating progress bar. So you can't just create a progressbar that displays the current upload.
You could create your own Ext.ProgressBar and estimate the upload time and when its done you set it to the max value. But I guess you don't want that.
To answer your question: You cannot simply track the current upload progress.
If you really need this user experience you can try a 3rd party component.
To quote the docs:
File uploads are not performed using normal "Ajax" techniques, that is
they are not performed using XMLHttpRequests. Instead the form is
submitted in the standard manner with the DOM element
temporarily modified to have its target set to refer to a dynamically
generated, hidden which is inserted into the document but
removed after the return data has been gathered.
To show real progress you can use onprogress callback of XMLHttpRequest:
Ext.override(Ext.data.request.Ajax, {
openRequest: function (options) {
var xhr = this.callParent(arguments);
if (options.progress) {
xhr.upload.onprogress = options.progress;
}
return xhr;
}
});
Then use like here:
Ext.Ajax.request({
url: '/upload/files',
rawData: data,
headers: { 'Content-Type': null }, //to use content type of FormData
progress: function (e) {
console.log('progress', e.loaded / e.total);
}
});
See online demo here.
buttons: [{
text: 'Upload',
handler: function () {
var form = this.up('form').getForm();
if (form.isValid()) {
form.submit({
url: '/upload/file',
waitMsg: 'Uploading your file...',
success: function (f, a) {
var result = a.result,
data = result.data,
name = data.name,
size = data.size,
message = Ext.String.format('<b>Message:</b> {0}<br>' +
'<b>FileName:</b> {1}<br>' +
'<b>FileSize:</b> {2} bytes',
result.msg, name, size);
Ext.Msg.alert('Success', message);
},
failure: function (f, a) {
Ext.Msg.alert('Failure', a.result.msg);
}
});
}
}
}]
Live demo with progress window is here

jquery form plugin with hash change

currently im having problems with the jquery form plugin. Part of this because i need to change the hash value on form submit. Heres the basic of what im doing:
$(document).ready(function() {
$('#search').ajaxForm({
target: '#pageContent',
success: function() {
$('#pageContent'); //this is all i need to 'ajaxify' this form
var hash = 'query='+encodeURI(document.getElementById('query').value);
window.location.hash = hash;
}
});
});
Now what happens is i am able to change the hash value but my form no longer 'ajaxify's itself and instead i just get a blank page..
What am i doing wrong?
since no-one had a suitable answer i managed to hack my implementation of jquery.history.js to allow searching via ajax.. heres the code:
$(document).ready(function() {
// bind form using ajaxForm
$('#search1').ajaxForm({
// target identifies the element(s) to update with the server response
target: '#pageContent',
// success identifies the function to invoke when the server response
success: function() {
$('#pageContent');
var hash = '#search.php?term='+($('#query').val()+'&submit=Submit').replace(/ /g, '+');
update(window.location.hash = hash);
}
});
});
i also replaced the spaces in the search to include + signs.. maybe this will help someone.
Try adding an actual hash, denoted by #:
$(document).ready(function() {
$('#search').ajaxForm({
target: '#pageContent',
success: function() {
var hash = '#query='+encodeURI($('#query').val());
window.location.hash = hash;
}
});
});

How to manipulate forms with Mootools

I'm trying to manipulate forms with Mootools. My purpose is to inject the response content of a form into a div element named result.
Here a code that works, but it replaces the content of the result div. This is not what I want : I want to ADD the form response content to the result div existing content. I just can't find on the web how to do this, and I've tried many things that are not working ... Please help
window.addEvent('domready', function() {
$('myform').addEvent('submit', function(e) {
e.stop();
var result = $('result').empty();
this.set('send',{
url: this.get('action'),
data: this,
onSuccess: function() {
result.set("html", this.response.text);
}
}).send();
});
});
If it's only text you want to add, just remove the empty method, and replace result.set() with result.appendText().
If you need to append an element tree, repeat the first step, and do:
onSuccess: function(){
Elements.from(this.response.text).inject(result);
}
Btw. It's all in the documentation - http://mootools.net/docs/core/Element/Element