Cannot access object properties in handlebars partial - node.js

I'm working on nodejs application. And want to display Mongoose result in web page. Template engine is express handlebars.
data= [
{name: 'some name', image: '/some_name.jpg', location: 'some location'},
{name: 'some name2', image: '/some_name2.jpg', location: 'some location2'},
{name: 'some name3', image: '/some_name3.jpg', location: 'some location3'}
]
I want to render data in handlebars partial. At first I'm iterating each object using #each and passing that object into the partial. Below is code how I'm doing.
{{#each data}}
{{> somePartial this}}
{{/each}}
In somePartial I want to access properties of the object.
<h5>Name: {{this.name}}</h5>
<h5>Image: {{this.image}}</h5>
<h5>Location: {{this.location}}</h5>
I can't see any value rendering in browser. In server console I get some warning or something like this Handlebars: Access has been denied to resolve the property 'xxxx' because it is not 'own property' of its parent..

Just use without this
{{> somePartial}}
...
<h5>Name: {{name}}</h5>
More info here: https://handlebarsjs.com/guide/partials.html#partial-parameters

To solve Handlebars: Access has been denied to resolve the property 'xxxx' because it is not 'own property' of its parent.
Map the result array in new array.
let result2 = result.map(val=>{
return {field1: val.field1,field2: val.field2, field3: val.field3 and so on}
})
For security reason handlebar does not allow to pass fetched result directly. You need to map with required field so that no sensitive data got passed.

Related

Data passed to Handlebars not showing

I want to display items from the database which I already log the result to the console. The console displays the result. but handlebars not displaying data.
This is controller
exports.createCategory = function(req, res, next){
knex('product_category')
.select()
.then(function(errors, result){
res.render('administration/category', { result, errors });
});
}
This is my router
router.get('/category', adminControllers.createCategory);
and this is my handlebar
<div class="col-md-4 col-lg-4">
{{#each result}}
<h1>{{category_name}}</h1>
{{/each}}
</div>
Just do debugging 101.
Add debug prints and check that you get correct data from DB and that it even executes.
Add to template some field to show you error too. Now if error is returned from query, nothing is shown.
Also add some static test attribute that you pass to template and print it to make sure that you are using handlebars template correctly.
I later got it.
Its the knex query.
after studying the knex docs and some online resources, I discovered I can also do this
knex('table').then(function(result)){
res.render('/', {result});
}
but I don't why this didn't work
knex('table').select().then(function(result)){
res.render('/', {result});
}

Access Object in Pug

i wanna to access at my var tab in my console on front
this is my backend code
let tab= global.queue.GetListOfTraitement();
res.render('index', { title: 'Express', test: tab});
the result in backend console
[ status {
Type: 'File',
NomFichier: 'F1504365806Mcmhs784.avi',
Depart: 1504880910657 },
status {
Type: 'File',
NomFichier: 'F1504364893Euyza324.avi',
Depart: 1504881249064 } ]
my pug file
extends layout
block content
h1= title
p Welcome to #{test}
h2= title
script.
console.log(test);
div
div
my result web page
Express
Welcome to [object Object]
Express
my result in console web
ReferenceError: test is not defined
my object is send has string [object Object] i can't acces of property of my object.
Can you help me please?
i have the solution, i can't show the index number with my console on backend, now i know i have index number
block content
h1= title
p Welcome to #{test[0].Type}
h2= title
table
But i always don't know how to pass object from backend to frontend.
You need to convert it to a string, with JSON.Stringify() then you can display the content of the object.

How to update an AngularJS directive when using $route and partials

http://jsfiddle.net/MTzJF/36/
The JSFiddle above is set up to explain the issue. But, basically:
HTML:
<breadcrumb></breadcrumb>
<div ng-view></div>
Angular Directive & Routing:
angular
.module('app', [])
.directive('breadcrumb', function() {
return {
restrict: 'E',
template: "<ul class='breadcrumb'><li ng-repeat='node in path'><a ng-href='{{node.url}}'>{{node.label}}</a></li></ul>",
replace: true,
controller: Ctrl1
}
})
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
template: '<h1>{{pgTitle}}</h1>',
controller: Ctrl2
});
}]);
Controllers
function Ctrl1($scope) {
$scope.path = [{
label: 'Home',
url: '#/'}];
$scope.pgTitle = "Home"
}
function Ctrl2($scope, $routeParams) {
$scope.path = [{
label: 'Home',
url: '#/'},{
label: 'Node 2',
url: '#/node2'}];
$scope.pgTitle = "Node 2"
}
​
I expect that changing $scope.path in Ctrl2 will update the breadcrumb directive, but it's not happening. I have to believe it has something to do with their relative scopes, but simply don't understand it well enough to see what. I've read dozens of articles and StackOverflow posts on it, but nothing is specific enough to let me see what I'm missing.
I'm hoping someone can point me in the right direction.
Thanks much!
nz
The reason your fiddle is not working is because ( like you rightly identified ) of scope issue. Your Ctrl1 is the Controller that controls the scope for your directive. The directive is looking for a variable called path which is an array of path's. If we have a look at the path variable in that scope it seems to be containing just 1 value inside of it.
function Ctrl1($scope) {
$scope.path = [{
label: 'Home',
url: '#/'}];
$scope.pgTitle = "Home"
}
Now you wish to change this variable path in another controller Ctrl2. I am assuming that you are attempting to have the scope of Ctrl2 "inherit" from the scope of Ctrl1. To achieve this, first check on which element Ctrl2 is defined. Is that element ( html element ) a child of the element of Ctrl1 ?
From your HTML :
Element of Ctrl1 : <breadcrumb></breadcrumb>
Element of Ctrl2 : <div ng-view></div>
For Ctrl2 to be child of Ctrl1 : your HTML structure should look like :
<breadcrumb>
<div ng-view></div>
</breadcrumb>
If we make this change to your code, it doesnt work yet. This is because when angular looks at the directive for <breadcrumb> it has no idea what it should do with the stuff that is inside of that node. <breadcrumb> is a html node. Since it is a node, it can contain content / other nodes inside of it. When you replace this breadcrumb node with the template, you should also give angular instructions to the effect : "If you find stuff inside of me, put it here". This is how you do it.
Modify your directive code to be :
.directive('breadcrumb', function() {
return {
restrict: 'E',
template: "<div><ul class='breadcrumb'><li ng-repeat='node in path'><a ng-href='{{node.url}}'>{{node.label}}</a></li></ul><div ng-transclude></div></div>",
replace: true,
transclude : true,
controller: Ctrl1
}
})
There are few differences / changes here.
Added an attribute called transclude to the directive object and set it to true.
Wrap the whole template so that it can be returned as a single HTML element.
Specify the place where you want the contents of the to go. Notice the ng-transclude. That is the place where the contents go.
You will notice now that the content is getting replaced now. Except the path is not getting updated with the path value from the child controller. Have a look at this https://stackoverflow.com/a/14049482/1057639 answer. It is an amazing explanation of scope / prototypical inheritance. Basically, your write to path is creating a new path variable in the child scope that is overshadowing the parent path ( which is being used by the directive).
Your best bet in this scenario is to create an addPath function in the parent scope and use it ( in child scopes ) to add new Path when you define new subviews.
Here is a fiddle that does all these.

Jade dynamic data

Using node.js I am passing some variables to jade view:
res.render('index', {
locals: {
name: user.name,
hashpassword: JSON.stringify(user.hashPass),
languages: JSON.stringify(langs)}
});
In jade file I have:
body
#heading
h1 nodechat
label !{locals.languages} // working - printing whole json string
#content
- var laangs = !{locals.languages} //not working here!
//SyntaxError: Unexpected token .
- each item in laangs
label= item.EnglishName
The problem is that I cannot pass locals.languages to a variable in jade file. If I assign it to a single html element (like label), it's working, but when I try with var = that doesn't work.
What may be the problem?
See my change below...
body
#heading
h1 nodechat
label !{locals.languages} // working - printing whole json string
#content
//- Do it like this...You're already in JavaScript land after the -
- var laangs = locals.languages
- each item in laangs
label= item.EnglishName
Change !{locals.languages} into locals.languages

Dynamic Links with Jade

Using Jade + Express + Node.js + Mongoose + MongoDB for my app, but this issue I ran into is likely in Jade:
I have some code as follows that prints a list of posts by title, author
div#articles
-each post in records
div.article
#{post.title} was written by #{post.author}
Link to Article
Now I want to the link in written Jade instead of HTML, but when I replace the line with
a(href='#{post.title}')
it links to /#{post.title} instead of the variable name such as /newpost1. Doing it as
a(href=#{post.title})
returns an error. I'm sure this is a syntax issue, but I can't find the solution in the GitHub documentation
pretty sure you can just do:
a(href=post.title)
jade:
- var records = [ { title: 'one', author: 'one' }, { title: 'two', author: 'two' } ];
div#articles
-each post in records
div.article
| #{post.title} was written by #{post.author}
a(href =post.title) Link to Article
html:
<div id="articles">
<div class="article">one was written by oneLink to Article</div>
<div class="article">two was written by twoLink to Article</div>
</div>

Resources