I am setting-up the server response of a query to couchbase and want to use handlerbars to render the response data.
I understand that the best practice is to have my helper functions into a separate file and not be embedded in a script tag in my html file.
My question is what is the best practice or technique to pass the data from the server response to my hanldbars helper file to then be manipulated?
I am using hapijs on the server and jQuery on the client.
Well I might be wrong, but following this example I found, it seems like you export the helper file like you would any other module with the module.exports
http://codyrushing.com/using-handlebars-helpers-on-both-client-and-server/
According to the API documentation for hapi the helper file must export a single method with the signature `function(context).
Helpers are functions used within templates to perform transformations
and other data manipulations using the template context or other
inputs. Each '.js' file in the helpers directory is loaded and the
file name is used as the helper name. The files must export a single
method with the signature function(context) and return a string.
Sub-folders are not supported and are ignored. Defaults to no helpers
support (empty path). Note that jade does not support loading helpers
this way.
https://github.com/hapijs/hapi/blob/master/docs/Reference.md#route-options
Related
Sorry if the title is misleading or vague, I couldn't really think of a good way to describe what I'm trying to do.
Basically, I have my index.js file calling another file via a require, we'll say it's js_functions.js.
js_functions.js is calling multiple files via require, and those individual files are all exporting functions correctly.
For sake of example, we'll say that the structure is index.js > js_functions.js > add.js.
Is there a way to call a function from add.js in index.js without directly requiring the add.js in index.js (via js_functions.js)?
If index.js wants to call a function from add.js, then you have two options:
index.js can require('add.js') directly and thus get the exported function from add.js to call.
js_functions.js can export the function from add.js so when you require('js_functions.js'), the function you want to call from add.js is available in the js_functions.js exports.
Generally, I avoid dual exporting as in option #2 and if I want a function from add.js, I just make the dependencies direct and clear require('add.js') so I can get access to that function.
If you're new to node.js module development, then it takes a little getting used to that you start every new module definition, but just adding all the require statements that you need to get access to the modules/functions you need. But, this is how you do module development in node.js and it has all sorts of benefits (testability, resuability, sharability, clear dependencies with no implicit dependencies, etc...). So, just get use to adding a little extra code at the start of each module to import the things you need.
Is there a way to call a function from add.js in index.js without directly requiring the add.js in index.js (via js_functions.js)?
Only if js_functions.js exports the function from add.js that you want to call. Just because js_functions.js has already done require('add.js') that does not provide access to the exports in add.js to any other code besides js_functions.js.
In the future, we can help you more accurately and quicker when you include the actual relevant code. We tend to do a lot better with specific questions that contain specific code than theoretical questions that try to use words (and no code) to describe some problem.
What is the best way to define custom functions in loopback api that can be used in models defined ?
For example a basic express application can have functions in helper folder on root directory, but doing same in loopback is not recommended and does not maintain loopback way.
Any help would be highly appreciated.
This is very well documented.
Custom logic can be placed in
boot scripts
middlewares
models:
remote methods
remote hooks
operation hooks
application-decoupled logic can very well be put in helper folders, separate folders at root level, etc. There is nothing wrong with modularizing your program this way, it is actually a good thing.
As mentioned by others, the Loopback documentation answers your question like this:
Adding logic to models - adding remote methods, remote hooks and operation hooks.
Defining boot scripts - writing scripts (in the /server/boot directory) that run when the application starts.
Defining middleware - adding custom middleware to the application .
That's a great answer if you have custom functions for a particular model, boot script, or middleware. And as Dharmendra Yadav said, mixins can be another option:
You can use mixins to perform different common actions on models such as observing changes using operation hooks and adding model attributes.
But what about code that simply doesn't fit into any of those categories?
I don't have experience with a lot of web frameworks, but one framework I have used is Grails, which is very opinionated and gives you a place for just about everything. And if your code doesn't fit into any of those categories, they give you a place for that too:
src/main/groovy - Supporting sources
So when I ran into this same problem in Loopback, I just created a src directory under server and that's where I put some helper classes that don't seem to fit anywhere else. And I include them as needed:
const HelperClass = require('../src/HelperClass');
HelperClass.helperFunction()...
Of course you can name the folder however you'd like: src, helpers, support, whatever. And then put it under common or server as appropriate.
The best way to define functions in loopback i found is to use mixins. Here is the sample way of doing so..
https://loopback.io/doc/en/lb3/Defining-mixins.html
You can inherit these defined mixins into your models through .json of your model with {mixins:yourmixin.js}, nice and easy.
Here's some sample code to get you headed in the right direction.
mynewmodel.js
http://domain/api/mynewmodel/myfunc.js
function myfunc(data, callback) {
// ** Put your code here **
console.log('myfunc');
}
function remoteMethod(model) {
model.remoteMethod(
'myfunc',
{
http: { verb: 'post' },
accepts: { arg: 'data', type: 'data' },
returns: [
{ arg: 'returndata', type: 'data' }
]
}
)
}
UPDATE
Generally your js files go in common/models
I'm new to node js. I searched a lot on stack overflow on this question below, none what I need.
I have an app.js file which initiates node server and a router file. I want to be able to store a global value once and shared across other server side .js files which contains my functions. I also want this variable to be accessible in my .jade file. (I use express BTW)
Is there a way to accomplish this?
Thanks.
The Node.js documentation says under Module Caching
Caching Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will
get exactly the same object returned, if it would resolve to the same
file.
Multiple calls to require('foo') may not cause the module code to be
executed multiple times. This is an important feature. With it,
"partially done" objects can be returned, thus allowing transitive
dependencies to be loaded even when they would cause cycles.
If you want to have a module execute code multiple times, then export
a function, and call that function.
Which means you can easily expose a global object simply by putting it in its own module.
//config.js
var config = {
dbUrl: 'mogodb://localhost:2107/persons'
};
module.exports = config;
And then when you want to gain access to that object, you simply do:
var config = require('./config');
And that's done, you get access to the same instance everywhere.
You'll want to limit the usage of global vars in Node. This is because unlike any other server side language, Node is a persistent process that share all request. So you cannot setup user state globally as those will be shared across all user accessing your site.
In raw node, there's two global context:
global.foo = 'bar';
// and the process object
process.some_var = 1;
In Express, you can setup application wide vars using app.set
But, most of the time you'll want to share data by adding them to the request or the response objects. That is because those objects are "user" specifics, unlike the global namespace.
For the template, you'll always want to pass in the context:
app.render('email', Object.assign( aSharedObject, {
specific: 'values'
}));
i would use process.env or if you are using nconf put it into the app configuration as Jordan said, globals are BAD idea, also if you don't want to include nconf or any other conf module or use process.env then you can create a module and export a set of getters and setters to handle the value
I have a directory with multiple js source files that is imported on client side webpage. I am also needing to import all of those sources files into server side node js app.
I have used the following approach so far
if( 'undefined' != typeof global ) {
module.exports = global.Class= Class;
}
The code is appended to the end of the source file
However I need to avoid editing the source files. Is there a good approach of how to import all of the classes contained the source folders? Instead of just running through the source files and having a modules.exports for each class? Also is there a way to give a directory to the require() call and have it import all the contained source files?
By exporting the objects into the global namespace you are kind of going against best standards in Javascript. The point in the module.exports is so that you can use requireJS to import the object that you need, rather than have every object available to you. So I'm afraid the answer is no, the require call only accepts single module references (due to the return value of the function assigning the object to a variable).
The 'good' approach would be to include a single file on the client that holds your main cilent code that references the modules/objects it needs to continue working. The source files will then be included as and when they are needed.
If you could modify the client side files, you could use this pattern: http://caolanmcmahon.com/posts/writing_for_node_and_the_browser/
file: tool.js
(function(exports) {
exports.Hello = function(name) {
console.log('Hello %s', name);
}
})(exports || window);
file index.js
require('./tool').Hello('username');
In an Dojo 1.7 AMD web app you can define also arbitrary data in the config object (http://dojotoolkit.org/reference-guide/loader/amd.html).
The configuration object can also be used to set arbitrary, application-specific configuration data. All properties of a configuration object are shallow copied to require.rawConfig
I looked to the requirejs config page (http://requirejs.org/docs/api.html#config), but I did not find a similar feature here. But I did not look into the source code.
Is there a possibility to store arbitrary infos in the requirejs config and get access to it?
Thanks alot in advance
Wolfgang
As far as I can see it is not supported.
You need to insert 1 line in the require.js source code to get this feature.
Here is an example:
require.config({
test: "one",
paths: {
'jquery': 'libs/jquery/1.7.1/jquery',
...
Along with the normal values you store your arbitrary information.
Then, you have to open the requirejs source code with a text editor.
Approximately in line 380 - 390 (depends on your version), function "makeRequire":
This function calls another called "mixin":
mixin(modRequire, {
nameToUrl: makeContextModuleFunc(context.nameToUrl, relModuleMap),
toUrl: makeContextModuleFunc(context.toUrl, relModuleMap),
defined: makeContextModuleFunc(context.requireDefined, relModuleMap),
specified: makeContextModuleFunc(context.requireSpecified, relModuleMap),
isBrowser: req.isBrowser,
rawConfig: config
});
After "isBrowser" write "rawConfig: config".
Now, in your amd module:
define(['require'], function (require){
alert (require.rawConfig.test);
...
Update:
This feature will be implimented in requirejs 1.1.
https://github.com/jrburke/requirejs/issues/182