I'm getting a rendering error in node.js with vash. I'm really struggling to see what the issue is. Below is the error and the code causing the error.
TypeError: Problem while rendering template at line 4, character 2.
Original message: object is not a function. Context: 2 |
#html.block('body', function(model){ 3 | <p>#model.title </p> > 4 |
}); 5 | }); 6 | 7 | at helpers.extend.model
(C:\Users\user009\Dropbox\cpp\node_modules\vash\build\vash.js:2213:4)
at Object.vash.loadFile
(C:\Users\user009\Dropbox\cpp\node_modules\vash\build\vash.js:2072:10)
at helpers.extend
(C:\Users\user009\Dropbox\cpp\node_modules\vash\build\vash.js:2190:8)
at eval (eval at <anonymous>
(C:\Users\user009\Dropbox\cpp\node_modules\vash\build\vash.js:1820:24),
<anonymous>:7:21) at vash.link.linked
(C:\Users\user009\Dropbox\cpp\node_modules\vash\build\vash.js:1860:12)
at vash.renderFile
(C:\Users\user009\Dropbox\cpp\node_modules\vash\build\vash.js:2082:21)
at Object.vash.loadFile
(C:\Users\user009\Dropbox\cpp\node_modules\vash\build\vash.js:2070:10)
at View.vash.renderFile [as engine]
(C:\Users\user009\Dropbox\cpp\node_modules\vash\build\vash.js:2078:8)
at View.render
(C:\Users\user009\Dropbox\cpp\node_modules\express\lib\view.js:76:8)
at Function.app.render
(C:\Users\user009\Dropbox\cpp\node_modules\express\lib\application.js:502:10)
router:
app.get("/", function (request, response) {
response.render('index', {title: 'letsdoit'});
});
layout.vash
<!DOCTYPE html>
<html>
<head><link href="/css/site.css" rel="stylesheet" />
<title>#model.title</title></head>
<body><div> #html.block('body') </div></body></html>
index.vash
#html.extend('layout', function(model){
#html.block('body', function(model){
<p>#model.title </p>
});
});
In your index.vash file, make sure the path to the layout.vash file is correct.
For example, if the views folder structure is views/home/layout.vash and views/home/index.vash, then:
#html.extend('layout', function(model){
should be:
#html.extend('home/layout', function(model){
hope it helps.
Related
i decided to go ahead and use the yahoo weather api, in an attempt for it to show the location and then the weather.
app.js code:
** note i replaced the api url location with the term 'query'**
var express = require("express");
var app = express();
var request = require("request");
app.set("view engine", "ejs");
app.get("/", function(req, res){
res.render("weatherSearch");
});
app.get("/results", function(req, res){
var query = req.query.searchTerm;
var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22"+query+"%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"
request(url, function(error, response, body){
if(!error && response.statusCode == 200){
var data = JSON.parse(body);
res.render("results", {data: data});
}
});
});
app.listen(process.env.PORT, process.env.IP, function(){
console.log("Server Connected");
});
weatherSearch.ejs :
<h1>Where would you like to check the weather?<h1>
<form action ="/results" method="GET">
<input type="text" placeholder="Enter the city here!" name="searchTerm">
<input type="submit">
</form>
results.ejs
<h1>The Weather is:</h1>
<ul>
<% data["query"].forEach(function(weather){ %>
<li>
<strong>
<% weather["location"] %>
</strong>
</li>
<% }) %>
</ul>
Search Again!
The error i receive from the console is:
Server Connected
TypeError: /home/ubuntu/workspace/WeatherSearchAPP/views/results.ejs:4
2|
3| <ul>
>> 4| <% data["query"].forEach(function(weather){ %>
5| <li>
6| <strong>
7| <% weather["location"] %>
data.query.forEach is not a function
at eval (eval at compile (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/ejs/lib/ejs.js:618:12), <anonymous>:11:22)
at returnedFn (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/ejs/lib/ejs.js:653:17)
at tryHandleCache (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/ejs/lib/ejs.js:251:36)
at View.exports.renderFile [as engine] (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/ejs/lib/ejs.js:482:10)
at View.render (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/express/lib/view.js:135:8)
at tryRender (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/express/lib/application.js:640:10)
at EventEmitter.render (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/express/lib/application.js:592:3)
at ServerResponse.render (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/express/lib/response.js:1008:7)
at Request._callback (/home/ubuntu/workspace/WeatherSearchAPP/app.js:19:21)
at Request.self.callback (/home/ubuntu/workspace/WeatherSearchAPP/node_modules/request/request.js:185:22)
yahoo weather api: (This currently gives the weather in 'london'), so if you copy this in to your web browser you'll see a vast amount of info pertaining to the weather in London.
https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22london%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys
if anyone has any suggestions on what i have done incorrectly that would greatly be appreciated!!
The API returns data in the format of { "query": { ...} }, translate this into a JSON object and you end up with a query object, not an array. Looking at the query object itself it does seem to have count and results properties (and the results property also looks like an object). However, your particular query only yields a single result, so assuming this yields an array in scenarios where you have more than one I presume you'll need to use a combination both of these properties to parse the data accurately e.g.
const data = JSON.parse(body);
const { count, results } = data.query;
res.render("results", {
results: count > 1 ? results : [results] // wrap in an array of only single result
});
Then in your view
<% results.forEach(...) %>
'forEach' is an array method and the Yahoo Weather API doesn't return an array under the key "query". Each API is different, and each request can yield different structured JSON data.
You can check how Yahoo Weather API response is structured by opening this link, as you mentioned. For example, if you want to access the city name, you would use
<%= data.query.results.channel.location.city %>
You get a forecast array returned for the upcoming days, on which you could use a forEach loop because it's an array: query.results.channel.item.forecast
In a scenario where you would want to loop over objects in JS, you can use the for...in loop: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
When I try to compile the following server-side code with
vue 2.5.13
node 9.9.0
I get an "unexpected token" error. I don't know why that is. I am simply trying to do an extrapolation. Unfortunately I can not codepen, because this is server side code. But the example is bare bones, so it should be possible to reproduce.
Here's the code:
const Vue = require('vue');
const renderer = require('vue-server-renderer').createRenderer();
let template = `<!DOCTYPE HTML>
<html lang="de" itemscope itemtype="http://schema.org/WebPage">
<head>
<meta charset="utf-8"/>
{{{meta}}}
<title>{{{title}}}</title>
</head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>`;
let app = new Vue({
data: {
meta: '<meta/>',
title: 'title'
},
template: template
});
renderer.renderToString(app, (err, html) => {
if (err) {
console.error(err);
}
console.log(html);
});
This is the error I get:
<!DOCTYPE HTML>
<html lang="de" itemscope itemtype="http://schema.org/WebPage">
<head>
<meta charset="utf-8"/>
{{{meta}}}
<title>{{{title}}}</title>
</head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>
- invalid expression: Unexpected token ) in
"\n "+_s({meta)+"}\n "
Raw expression: {{{meta}}}
- invalid expression: Unexpected token ) in
_s({title)+"}"
Raw expression: {{{title}}}
(found in <Root>)
at onCompilationError (/path/node_modules/vue-server-renderer/build.js:7378:9)
at compileToFunctions (/path/node_modules/vue-server-renderer/build.js:5536:9)
at normalizeRender (/path/node_modules/vue-server-renderer/build.js:7388:22)
at render (/path/node_modules/vue-server-renderer/build.js:7752:5)
at Object.renderToString (/path/node_modules/vue-server-renderer/build.js:8232:9)
at Object.<anonymous> (/path/playground/vue-render.js:24:10)
at Module._compile (module.js:649:30)
at Object.Module._extensions..js (module.js:660:10)
at Module.load (module.js:561:32)
at tryModuleLoad (module.js:501:12)
Looking at the section on Template Interpolation in SSR guide. I think {{{title}}} in your code ought to be {{title}} (two instead of three curly brackets) since its just a string and not HTML.
The forward slash in <meta/> probably needs to be escaped.
Trying to switch out Mongo and put in Postgres (in other words, similar code worked fine with Mongo). Getting Cannot read property 'length' of undefined on the following code. I'm sure it's simple but I'm new to this whole stack so having trouble tying it together. Not a lot of examples on knex, so even though the docs are pretty good, I'm having trouble finding an example to copy.
I'm obviously pulling the right data but am stuck on how to get jade to display it.
Stack: Node/Express/Knex/Postgres/Jade
users.js
router.get('/', function(req, res, next) {
db.select().from('users').limit(1)
.then(function(users) {
console.dir(users)})
.then(function(users) {
res.render('users', {users: users})})
.catch(function(error) {
console.error(error)
})
});
users.jade
extends layout
block content
h1 Users
ul
for user in users
p
input(type="text", name="name", value="#{user.name}")
input(type="text", name="admin", value="#{user.admin}")
input(type="text", name="smsNumber", value="#{user.smsNumber}")
console
[ { uid: 1,
name: 'Don',
admin: 'true',
smsNumber: '4077023951',
created_at: null,
updated_at: null } ]
browser at localhost:3000/users
C:\Users\dvande03\Personal\dailychallenge\views\users.jade:6 4| h1 Users 5| ul > 6| for user in users 7| p 8| input(type="text", name="name", value="#{user.name}") 9| input(type="text", name="admin", value="#{user.admin}") Cannot read property 'length' of undefined
TypeError: C:\Users\dvande03\Personal\dailychallenge\views\users.jade:6
4| h1 Users
5| ul
> 6| for user in users
7| p
8| input(type="text", name="name", value="#{user.name}")
9| input(type="text", name="admin", value="#{user.admin}")
Cannot read property 'length' of undefined
at eval (eval at <anonymous> (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:218:8), <anonymous>:51:31)
at eval (eval at <anonymous> (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:218:8), <anonymous>:106:4)
at eval (eval at <anonymous> (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:218:8), <anonymous>:119:22)
at res (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:219:38)
at Object.exports.renderFile (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:380:38)
at Object.exports.renderFile (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:370:21)
at View.exports.__express [as engine] (C:\Users\dvande03\Personal\dailychallenge\node_modules\jade\lib\index.js:417:11)
at View.render (C:\Users\dvande03\Personal\dailychallenge\node_modules\express\lib\view.js:126:8)
at tryRender (C:\Users\dvande03\Personal\dailychallenge\node_modules\express\lib\application.js:639:10)
at EventEmitter.render (C:\Users\dvande03\Personal\dailychallenge\node_modules\express\lib\application.js:591:3)
at ServerResponse.render (C:\Users\dvande03\Personal\dailychallenge\node_modules\express\lib\response.js:961:7)
at C:\Users\dvande03\Personal\dailychallenge\routes\users.js:11:13
at tryCatcher (C:\Users\dvande03\Personal\dailychallenge\node_modules\bluebird\js\main\util.js:24:31)
at Promise._settlePromiseFromHandler (C:\Users\dvande03\Personal\dailychallenge\node_modules\bluebird\js\main\promise.js:454:31)
at Promise._settlePromiseAt (C:\Users\dvande03\Personal\dailychallenge\node_modules\bluebird\js\main\promise.js:530:18)
at Promise._settlePromises (C:\Users\dvande03\Personal\dailychallenge\node_modules\bluebird\js\main\promise.js:646:14)
res.render should look like this: res.render(view [, locals] [, callback]), where locals is an object whose properties define local variables for the view.
In your case that means changing the line where you render to:
res.render('users', {users: users})
You pass an object with local variables to render. In the jade-file you use the keys in the object when you want to refer to the values.
Solved it but I don't completely understand why. I commented out the console.dir before the render and it works. Is that because the users in the console.dir .then didn't pass to the render .then?
I accepted the answer above too because without that, I couldn't have gotten here. Thank you #tomtom.
I am using express-ejs-layouts and am seeing the following error in the console log:
>> 5| <title><%= title %></title>
title is not defined
I do indeed have the following element defined in my layout.ejs file:
<title><%= title %></title>
I am populating this variable from one of my route files:
router.get('/', function(req, res) {
res.render('index', {
title : 'Express'
});
});
Any idea what I am missing? Thanks!
I figured this out. There was another variable (description) that was not defined. As soon as I set the 'description' variable this worked. Seems a bit odd that the error message would be for 'title' though.
i am using backbonejs with node js trying to pass variable from backbone view to template(html file). function for rendering view template is like this :
render: function(event){
var compiled_template = _.template( $("#results-template").html() );
console.log(myPhoto.toJSON());
$(this.el).html(compiled_template(myPhoto.toJSON()));
return this;
}
myPhoto having a value :
{
src: 'placeholder.jpg',
title: 'an image placeholder',
coordinates: [0,0],
tags: ['untagged'],
location: 'home'
}
and in html file :
<script id="results-template" type="text/template">
<h2><%= title %></h2>
<p>testing....</p>
</script>
when i am execute it gives an error like
ReferenceError: c:\trello\testApp/views/test.html:19
17| <script id="results-template" type="text/template">
18|
>> 19| <h2><%= title %></h2>
20| <p>testing....</p>
21| </script>
22|
title is not defined
at Object.<anonymous> (eval at <anonymous> (c:\trello\node_modules\ejs\lib\ejs.js:203:1))
at Object.<anonymous> (c:\trello\node_modules\ejs\lib\ejs.js:201:15)
at ServerResponse._render (c:\trello\node_modules\express\lib\view.js:425:21)
at ServerResponse.render (c:\trello\node_modules\express\lib\view.js:318:17)
at c:\trello\testApp\test.js:23:16
at callbacks (c:\trello\node_modules\express\lib\router\index.js:272:11)
at param (c:\trello\node_modules\express\lib\router\index.js:246:11)
at pass (c:\trello\node_modules\express\lib\router\index.js:253:5)
at Router._dispatch (c:\trello\node_modules\express\lib\router\index.js:280:4)
at Object.handle (c:\trello\node_modules\express\lib\router\index.js:45:10)
how to solve this???
Are you sure all your photos have a title? Empty properties can cause this error. You can fix this by adding default values (empty strings for example) in your backbone Model class.