I'm generating a handlebars view with hbs for express js framework, and I need to access the variables I pass to the view from inside a separate JavaScript file.
For example:
var foo = {{user.name}}
Obviously this code throws an error, but what is the preferred way of getting hbs variables inside JavaScript?
Currently I'm running another ajax request to get the same data. but I think it is not wise to make another request for the same data...
Found the solution, seems like i just had to put the handlebars variable inside a string for it to work.
In order to pass and Object to a variable I created hbs helper:
hbs.registerHelper('json', function(context) {
return JSON.stringify(context);
});
and the in my view:
var currentUser = JSON.parse('{{{json user}}}');
and now i can access the data on the client side js.
Related
I have a Handelbars app that loads data from javascript and partials for the templates. To get the templates to work I use the following in the Javascript:
var data = require('partials/data.js');
Handlebars.registerPartial('data', data);
Then in my partial I am able to do:
{{> data }}
I have a Handelbars variable I can use in my main template but I want to pass it down to the partial. With my other partials that don't register via the Javascript this is possible. I am assuming I need to pass this variable down like I do the templates?
As per the handlebars documentation, you should be able to simply pass the variable down as a parameter, like so:
{{> data parameter=variable }}
I am using node js , express. I am trying to call a function in template literal.
I made a module and import in main file and then add the function to app.locals and accessing in my views that works fine. But when i try to use it in template literals and also in my public file it give me error "currencyToWords is not defined".
I think in public file it makes sense because i make public folder static.
but in my views it is weird because when i use it in html it works but when i use it in template literal it gives error.
I want to use the currencyToWords function in template literals to change the response.
I have one solution that i can make the file in public folder and add the function in script in that file and import in footer but i dont want to do that.
Can anybody help me in solving the issue.
My app stucture
module.exports = { currencyConverter }
In app.js
app.js is my main file where i create server
var { currencyToWords } = require('./config/functions');
app.locals.currencyToWords = currencyToWords;
by adding in locals i can access it in my application any where
This code is working:
<div class="fix pull_right">
<h3><%= currencyToWords(property.propertyDetails.price)%></h3>
</div>
This is not working
var a =`
<p>${currencyToWords(property.propertyDetails.price)}</p>
`;
the above code is same but only difference is first one is use in ejs tags and second in ejs and template literals.
Here is the documentation from express about app.locals
app.locals
The app.locals object has properties that are local variables within the application.
console.dir(app.locals.title)
// => 'My App'
console.dir(app.locals.email)
// => 'me#myapp.com'
Once set, the value of app.locals properties persist throughout the life of the application, in contrast with res.locals properties that are valid only for the lifetime of the request.
You can access local variables in templates rendered within the application. This is useful for providing helper functions to templates, as well as application-level data. Local variables are available in middleware via req.app.locals (see req.app)
app.locals.title = 'My App'
app.locals.strftime = require('strftime')
app.locals.email = 'me#myapp.com'
I have set up a resource controller in Laravel with the following index function:
public function index()
{
if (!Auth::check()) {
return redirect()->route('login');
}
$decks = Auth::user()->decks->sortByDesc('name');
return view('decks.index')->with('decks', $decks);
}
On a different page I also need the $decks variable via a AJAX call. Right now I have set up an additional route to my controller, from which I can retrieve the decks via a GET request:
public function getDecks()
{
if (!Auth::check()) {
return;
}
$decks = Auth::user()->decks->sortByDesc('name');
return response()->json($decks);
}
My question: Is there a way to get the $decks variable via a request directly to index or is my solution the way to go?
If I make a get request to index I get the HTML of the decks.index view, but how can I access (if possible) the $decks variable?
I guess what I don't really grasp is this: What happens to $decks in the ->with('decks', $decks) statement? I know I can then access $decks using blade syntax on that page, but from where does it access the data and can I also access it via AJAX?
Yes! You can return different results depending on what kind of request was done. There is no need for 2 routes:
public function index(Request $request)
{
$decks = Auth::user()->decks->sortByDesc('name');
if ($request->ajax()) {
return response()->json(['decks' => $decks]);
} else {
return view('decks.index')->with('decks', $decks);
}
}
#Sven Hakvoort is right, you should check for authentication in the route definition:
Route::group(['middleware' => 'auth'], function () {
Route::get('/decks', 'DecksController#index');
// ... some other routes which requires authentication
}
You can not retrieve the $decks from the index route directly. When you call view(..)->with(...) it is internally passed to the blade template processor which also receives the $decks variable, the HTML is then build on the server-side and the 'compiled' HTMl is then returned to the browser. So once the server returns the result the $decks variable is not present anymore. Because of this behavior it is not possible to do what you want.
So yes, your solution is the way to go, although you might consider wrapping the Auth::check() in a middleware and move the call to $decks to a separate function in order to simplify your code.
I hope this answers your question, if anything is unclear feel free to ask!
Your solution is the proper way. It is not typically a good idea to handle any business logic or data retrieval using your routes - using a controller is preferred, which is what you are doing. If you want to avoid the if (Auth::check()) statement in your controller, you could add the auth middleware directly to that route like this.
Route::get('example', 'YourController#index')->middleware('auth');
Regarding your question about ->with('decks', $decks):
That function is sending your $decks variable to the view to be rendered in the blade template. That data is used by the server to render the page, and then the variable is discarded. If you want to also be able to work with that data on your page using javascript, you could do something like this in your blade template.
<script>
var decks = {!!$decks->toJSON()!!};
</script>
To the handlebars (version 1.0.0-rc.3) template I am passing two variables , one is the json and the other one is the string containing the current language on site.
self.template = template({ data: self.model, lang:self.lang });
Then inside the template file I have the following structure:
{{#each data}}
//this is working
{{../lang}}
{{#if this.title}}
{{this.desc}}
//i've tried this
{{../lang}}
//and this
{{lang}}
{{/if}}
{{/each}}
...but I couldn't access the lang value inside the if statement. What am I doing wrong?
I know you already solved your issue with a workaround but registering a Helper for doing a native way is cumbersome.
The thing is that every Handlebars helper overwrites the context and nest the new one inside the parent one, so you have to go up uone step further, like a UNIX like directory.
So, to access lang inside an each->if you have to use:
{{ ../../lang }}
I've find a solution by creating a handlebars helper function:
Handlebars.registerHelper('language', function() {
return self.lang; });
Then in the template i could use {{language}}
where ever I want.
I have an Ember.js app that gets its data from a JSON resource, and puts it into an ember-data model (Not sure about the terminology) for use in a Handlebars.js view. When I try to put the data into the template context, I get this error:
TypeError: arrangedContent.addArrayObserver is not a function
I've made a Fiddle to demonstrate it. Use the actual Fiddle to view the code, use the following link to see the error (which makes it try to put data into the template/view):
http://fiddle.jshell.net/WZ4vt/show/#/item/1
s = App.store.find(App.Item, 1);
s.get('value1');
The above works fine, and returns "test".
I updated the fiddle: http://jsfiddle.net/WZ4vt/3/
Your mistake was to declare your ItemController as ArrayController, but your Data Store just returned a single entity. I fixed that and additionally your Handlebars Template, as this was not working either.
So this is the new controller declaration:
ItemController: Em.Controller.extend(),
And the updated Template:
<script type="text/x-handlebars" data-template-name="item">
{{content.value1}}
{{content.value2}}
</script>
Here the working link: http://fiddle.jshell.net/WZ4vt/3/show/#/item/1