Using a promise in a view file

67 views
Skip to first unread message

Randall Meeker

unread,
Oct 7, 2014, 10:23:42 AM10/7/14
to sai...@googlegroups.com
Trying to access a model in a view file, but it returns a promise. Any idea on how to access models directly in view files?

David Lai

unread,
Oct 7, 2014, 3:13:27 PM10/7/14
to sai...@googlegroups.com
I think you want to resolve the promise before you process the view.

Randall Meeker

unread,
Oct 7, 2014, 3:28:28 PM10/7/14
to sai...@googlegroups.com
Of course I want to resolve it, otherwise I don't get my value. What is the point of Model's being globally accessible to the view if they can't be used inside the view?

I have some view pages that are shared among different controller/actions, but contain choices generates from models. I'm trying to figure out if I have to re-write the code to attach this info in every controller/action or if I can attach specific data to the view file itself. 

David Lai

unread,
Oct 7, 2014, 4:43:18 PM10/7/14
to sai...@googlegroups.com
I don't think you want views to consume models directly.  You'll probably want to map values to an intermediate object or something, then pass it in via controller.  My understanding is a true MVC, views are agnostic of the data model, and it's the controller's or view model's responsibility to feed it.

Randall Meeker

unread,
Oct 7, 2014, 4:56:57 PM10/7/14
to sai...@googlegroups.com
David, I appreciate your response and your engagement but your missing the point. You are correct about the true MVC, however I'm straight asking how do it do this (right or wrong). I appreciate that you don't want me to do this, but trust me when I say that I would like too try if possible. If you have a better method for me to achieve my stated goal of not rewriting the same code everytime I want to use the same partial in different view files, please let me know.

Again this is based on the fact that sails has made Models available in the view, but they can't be used. Why are they available if they can't be used, or can they?

Rob Wormald

unread,
Oct 7, 2014, 5:44:07 PM10/7/14
to Randall Meeker, sai...@googlegroups.com
Actually, David is spot on.

Fetching models is an asynchronous operation, regardless of whether you do it with promises or callbacks. Makes no difference, and doesn’t make much sense in any case to expose the Model (as opposed to the result of a model query) to the view…

What you probably want to do is some sort of utility method (a service would be a good place for this, assuming you want to use it on multiple controllers.

The promise version of something like this might look like:

// in services/RenderUtility.js

module.exports.renderData = function(data){
return res.view(’some/view’, { data: data });


//usage looks like

Foo.find().then(RenderUtility.renderData);

or for a bit more configurability, you could declare a function that returns a function:

module.exports.renderData = function(viewName){
return function(data){
res.view(viewName,{data: data});
}
}

which you could use like

Foo.find().then(RenderUtility.renderData(‘some/view’));

note the difference there where i’m calling the function inside the promise resolution.

R

Rob Wormald

unread,
Oct 7, 2014, 5:44:58 PM10/7/14
to Randall Meeker, sai...@googlegroups.com
And models are globally accessible to *controllers*, not views, AFAIK.

Randall Meeker

unread,
Oct 7, 2014, 6:05:46 PM10/7/14
to sai...@googlegroups.com, randal...@gmail.com
Rob, David was correct about MVC and I told him so. And just so we are clear, I don't want to start a debate about MVC as I have in different platforms for whatever very good reason used my models directly inside my view and so far I have not developed any plague like diseases. 

Your example is nice and thought out, however it seems a little single use. I could expand upon my previous example (Was trying to keep it simple.) Lets say 4 different partials on my website and they each have different information pulled from different models. Some appear on some pages and some appear on others and some pages have all 4. What I'm looking for is a way to tie information directly to those partials so that no matter where those views are they can have access to their information.

The only (non ajaxy) way I can see to do this is with policies that tie the information to the req.locals scope and then I specify in my policy definition what data needs to be available to the view. 

And yes Models are accessible from inside the views. So for the sake of repetition, why are they available if they can't be used, or can they?

Ambroise Dhenain

unread,
Oct 7, 2014, 6:10:06 PM10/7/14
to Randall Meeker, sai...@googlegroups.com
I also agree than even if it doesn't respect the MVC pattern, sometimes it's just much better to make the queries from the view, especially while using a loop to get data based on a specific item without having to store it before and send it from the controller. Just easier. Don't know if it's possible or not tho.
--
Cordialement,

M. Ambroise Dhenain.

Rob Wormald

unread,
Oct 7, 2014, 6:14:53 PM10/7/14
to Randall Meeker, sai...@googlegroups.com
No desire to debate either (especially about the semantics of MVC…) but that’s not why it doesn’t work - it’s how nodeJS works (not specific to Sails).

All DB type operations are asynchronous in node, and that’s the primary difference between other platforms and NodeJS. So callbacks or promises, you have to fetch the data, wait for it to complete that operation, and then render the view. 

If you’ve got an example of Models (that is, Model classes as opposed to instances of models you’ve fetched) being used in views in Sails/Express/Node I’ll happily eat my words and work up a better solution, but it goes against more or less everything I know about Node.

Discuss?

Randall Meeker

unread,
Oct 7, 2014, 6:29:52 PM10/7/14
to sai...@googlegroups.com, randal...@gmail.com
Oh, I have no example of them being used inside views in other node frameworks (as sails is the only one I have used so far). In other frameworks I have been able to use them inside, or they have the concept of partials (or includes) that can be tied to different controllers or helpers where data can be retrieved data to be used. This keeps the whole project very dry and modular. I just can't see how Sail solves for this common use case. I did notice that models were accessible from within the views and thought I would ask how people were using them within their views. It seems now that this is an oversight and (at least with waterline) there is no way to use the model within the view (to retrieve information anyway, you could always alter your data I suppose). 

It seems the only way to use the concept of a partial is to let sails know before hand (in a policy or something) that the partial is going to be called and that it needs to tie the corresponding data to the req object or something so that I can be used when rendering the view. Or at least that the most dry method I could come up with. 

David Lai

unread,
Oct 7, 2014, 6:34:32 PM10/7/14
to sai...@googlegroups.com, randal...@gmail.com
The view (template) in this case is interpreted by the template engine.  Since we have no control over it's execution since we're agnostic what's going on inside.  The responsibility is on us to provide the view with all the data it needs.  So it's best to only pass in POJOs.

In browserside frameworks like Angular, you have the luxury of having observers and databinding to update when the promise resolves.  On the serverside, you need to send out the entire response all at once, the browser will not be able to access the model directly.

There are some trickery you can do if you want to send an initial response with the HTML with a jsonp callback to fetch the completed query.  But at that point, you're better off going with a Single Page App on the client side and not use the server side templates at all.

Alberto Souza

unread,
Oct 7, 2014, 6:35:42 PM10/7/14
to Randall Meeker, sai...@googlegroups.com
Yes, you cant use Models query in Views ... but you can preload the dada and save in req.locals['youtVarName'] and it will be acessible as youtVarName in your template.

Normaly i change the controller to preload my data ... and override default automatic sails controller ..

David Lai

unread,
Oct 7, 2014, 6:42:59 PM10/7/14
to sai...@googlegroups.com
On the topic of reuse of fields on models displayed on multiple pages.  There are several ways I can think of of handling it in sails.

- You can use the hasMany/belongsTo features of models.  Say a User can have many posts, and many comments, a post and comment can have a belongs to relation to conveniently access their owners.

- You can use Service for fetching commonly use items.

- You can use something like lodash's extend mechanism to create a controller mixin, and use inheritance to handle reusability in a mixin sort of way.  https://lodash.com/docs#assign


Randall Meeker

unread,
Oct 8, 2014, 2:56:21 PM10/8/14
to sai...@googlegroups.com

Randall Meeker

unread,
Oct 8, 2014, 3:24:30 PM10/8/14
to sai...@googlegroups.com
Its also a much better description that i was giving of the same sort of problem. I went about describing it wrong

Alberto Souza

unread,
Oct 8, 2014, 3:29:53 PM10/8/14
to Randall Meeker, sai...@googlegroups.com
Randal ... i think is better use sails police or hook .

if I'm not mistaken the customMiddleware not work with socket.io

germ...@gmail.com

unread,
Dec 26, 2016, 9:46:33 AM12/26/16
to sails.js, randal...@gmail.com
Hi Randal, I believe I understand what you need. I'm in the same situation, how did you finally solve this?

Luis Lobo Borobia

unread,
Dec 31, 2016, 11:00:40 AM12/31/16
to sails.js, randal...@gmail.com
It would really help if you are more specific on what kind of data you want to retrieve each time. 

If you really want to use promises you have to get a view engine that supports it. If you are using ejs, you can try https://www.npmjs.com/package/ejs-promise

The other way as Alberto said, use a Policy or Hook.

Regards
Reply all
Reply to author
Forward
0 new messages