Read and transmit JSON file from Express to Jade - json

I'm new to Express and Jade, can't find why Jade tells me the object is undefined.
I've a big JSON file about a collectionable card game, which structure is:
{
"LEA" : { /* set data */ },
"LEB" : { /* set data */ },
"2ED" : { /* set data */ },
...
}
and, for each set
"name" : "Nemesis",
"code" : "NMS",
"gathererCode" : "NE",
"oldCode" : "NEM",
"magicCardsInfoCode" : "ne",
"releaseDate" : "2000-02-14"
"border" : "black",
"type" : "expansion",
"block" : "Masques",
"onlineOnly" : false,
"booster" : [ "rare", ... ],
"cards" : [ {}, {}, {}, ... ]
I want to loop through the array of cards for a GETed set and display some informations about. This is my cards.js file
'use strict';
var express = require('express');
var router = express.Router();
var mtgjson = require('mtgjson');
router.get('/:set?', function(req, res){
var set = req.params.set;
if (set === undefined) {
res.send('respond with a resource');
} else {
mtgjson(function(err, data) {
if (err) return console.log(err);
res.render('cards', { selectedSet : data.set });
});
}
});
module.exports = router;
and this the jade template
extends layout
block content
h1 #{selectedSet.name}
ul
each card in selectedSet.cards
li #{card.rarity}
I'm getting
Cannot read property 'name' of undefined
Any suggestion will be much appreciated, I'm probably making some stupid error.
EDIT: New informations ------------------
When I console.log(data) I get the following, it seems right:
TOR:
{ name: 'Torment',
code: 'TOR',
magicCardsInfoCode: 'tr',
releaseDate: '2002-02-04',
border: 'black',
type: 'expansion',
block: 'Odyssey',
booster:
[ 'rare',
'uncommon',
...
'common' ],
cards:
[ [Object],
[Object],
[Object],
...
[Object],
[Object],
[Object] ] },
And if I console set It gives me the right string ( TOR in this example ).
Edit 2 -------------------------
If I pass the entire data object and the set variable to the jade template, I can achieve the final result but in a very sub-optimal way.
I've made something like this
block content
ul
each val, key in data
if key == set
li #{val.name}
each card in val.cards
p #{card.name}
SOLUTION ----
Just a stupid error: I just messed up with property accessors. I should use data[set] instead of data.set beacause var set is a literal.
See reference http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.1

You need to use selectedSet.cards.rarity instead of cards.rarity. The only object you are passing to the template is your selectedSet object, and cards is nested within that.

I was using the wrong notation to access properties. I should use square brackets notation beacause the var set is a string literal, in this case the dot notation won't work.
See reference

Related

Trying to use request with ES6 + Webpack, but I am getting an error

I am currently trying to create a webapp with React, and I am trying to make a request to my server (with request). However, whenever I try to webpack the app I get an error. I am almost certain it has to do with request having to be labeled as an external library, but I can't get it to work. Can anybody help me?
Here is my webpack config.
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var extractCSS = new ExtractTextPlugin();
module.exports = {
entry : [
'./js/index.js'
],
output : {
path : __dirname + '/lib/',
publicPath : 'http://localhost:8080',
filename : 'bundle.js'
},
plugins : [
new ExtractTextPlugin('app.css'),
new webpack.NoErrorsPlugin()
],
module : {
loaders : [
{
test : /\.js$/,
loaders : [
'babel'
],
exclude : /node_modules/
},
{
test : /\.(jpe?g|png|gif|svg)$/i,
loaders : [
'url?limit=8192',
'img'
]
},
{
test : /\.scss$/,
include : /styles/,
loader : extractCSS.extract([
'css',
'autoprefixer',
'sass'
])
}
]
},
resolve : {
extensions : ['', '.js', '.json']
},
externals : {
request : 'request'
}
};
and here is the error that I am getting
ERROR in ./js/services/comic
Module parse failed: /Users/matthew.pfister/IdeaProjects/web/js/services/comic Line 1: Unexpected token
You may need an appropriate loader to handle this file type.
| import request from 'request';
|
| export default {
# ./js/creators/comic.js 11:21-49
Here is the file it is referencing
import request from 'request';
export default {
...
};
I dont think export default {...} is valid. try
var o = {...}
export default o
should work.
I just realized that the file that is throwing the error doesn't have the .js extension.
::facepalm:: everything is fixed.

Complicated nested json loops to store with extjs

I'm using a geojson extracted from naturalearthdata which looks like that :
All I want is to catch the NAME of each feature in order to display them in a grid (live search grid.. BTW is it efficient for 2000 names?)
But I can't access to all the name with root property. I tried to loop into all the features
Ext.define('myApp.store.Places', {
extend: 'Ext.data.Store',
alias: 'store.places',
requires : ['myApp.model.PlacesModel',
'myApp.view.main.MainModel'],
id: 'Places',
model: 'myApp.model.PlacesModel',
autoLoad: true,
proxy: {
type: 'ajax',
url : '/resources/data/coord.json',
reader: {
type: 'json',
transform: {
fn: function(data) {
for(var i = 0; i < data.features.length -1; i++){
names_places.push(data.features[i].properties.NAME);
}
debugger;
return names_places;
},
scope: this
}
}
}
});
But the debugger sent me that result which I don't understand :
Especially when the array looks good :
What is the good way to catch only the NAME? Does the return has to look to a json?
You can use the mapping attribute on the fields array in your model definition to map the correct attribute in the json to a field.
You set the rootProperty to features for the reader.
Then in your fields array something similar to this
fields: [
{ name: 'myCustomField', mapping: 'properties.NAME' }
]

extjs error on filling store

I have a java map. I converted it to json string and I obtain something like this :
{"NEW ZEALAND":"111111111111111","CHAD":"1","MOROCCO":"111","LATVIA":"11"}
Now I want to use it in a store and then a chart like the following code but it's not working. I have no error just no display.
var obj = Ext.Ajax.request({
url: App.rootPath + '/controller/home/dashboard/test.json',
method:'GET',
success: function(response) {
return Ext.JSON.decode(response.responseText);
}
});
var store2 = Ext.create('Ext.data.Store', {
model: 'PopulationPoint',
data: obj
});
Ext.create('Ext.chart.Chart', {
renderTo: 'infos2',
width: 500,
height: 300,
store: store2,
series: [
{
type: 'pie',
field: 'population',
label: {
field: 'state',
display: 'rotate',
font: '12px Arial'
}
}
]
});
The AJAX request is asynchronous. As such, the obj variable used to initialize your data won't contain your data yet.
One option is to create the store2 variable and create the chart directly in the success callback of the AJAX request.
A cleaner option would be to configure the store with a proxy to load the url, and in the callback create the chart.
EDIT
The JSON response does not contain the fields that are declared in your model (sent in the comments). Update the JSON to return a properly formatted model and the chart should work as seen in this fiddle. The JSON should look something like
[
{
"state" : "New Zealand",
"population" : 111111111
},
{
"state" : "Chad",
"population" : 1
}
]

Collection - Model usage for JSON response?

Regarding the pattern Backbone uses for Collections and Models , I am not sure if what I am trying to achieve is possible.
I am wanting the Collection to act as a constructor by making a AJAX POST request to fetch JSON. Using that JSON response it will instantiate multiple models and add them to an array.
Each object has the attributes which will be stored in my model e.g.
define([
'underscore',
'backbone'
], function (_, Backbone)
{
'use strict';
var Employee= Backbone.Model.extend({
defaults: {
name: '',
skill: '',
latitude : 0,
longitude : 0
},
});
return Employee;
});
JSON Response
[
{
"name" : "bob",
"skill" : "project manager",
"latitude" : 12512.25,
"longitude" : 95952.26
},
{
"name" : "sarah",
"skill" : "software dev",
"latitude" : 89432.25,
"longitude" : 1205.26
},
{
"name" : "tom",
"skill" : "evil sys admin",
"latitude" : 1215,
"longitude" : 92325
}
]
Collection
define([
'underscore',
'backbone',
'models/employee'
], function (_, Backbone, Store, Employee) {
'use strict';
var Employees = Backbone.Collection.extend({
// Reference to this collection's model.
model: Employee,
});
return new Employees();
});
Code
emps = new Employees();
emps.url("/testURL"); //
emps.sync();
emps.model[0]; //undefined !!!
So from that I can conclude that the Collection is not smart enough to instantiate an array of Employee models from the JSON response.
How can I do this?
The function you're looking for is fetch. Fetch uses sync to fetch data, and then instantiates models accordingly.
If your API doesn't respond to a GET /someurl then what you need to override is the sync method. Read the source to see how it works.
Also, you're not using url properly. It should be a string, or a function that returns a string.
var employees = new Employees();
employees.url = '/my/testurl';
// note that fetch is async
employees.fetch().done(function () {
console.log(employees.length);
});
Right now your collection constructor code is getting undefined as its input array, and thus remains empty.
You want to pass your collection into your Employees constructor, like
var emps = new Employees(arrayOfEmployees, {model: Employee});
Also, that last part (re-specifying the model) is likely not necessary.

create dijit accordian container from foreach loop with data returned from json

how do i use a for each loop to create accordian containers for each data returned from json file using ajax ?
i have tried this ! is it the way to it ?
dojo.xhrGet({
url:"json/"file_Name".json",
handleAs: "json",
timeout: 10000,
load: function(response,details){
container(response)},
error: function(error_msg,details){
container(error_msg, details);
}
});
//how do i use the json file to add data to the array arrFruit and then create dijit accordian container for every data in the array//
container = function(array, domConstruct) {
var arrFruit = ["apples", "kiwis", "pineapples"];
array.forEach(arrFruit, function(item, i){
domConstruct.create("li", {innerHTML: i+1+". "+item}, "properties");
});
};
//the response data from my json file is:-
[
{
"itemId": 1234,
"Name": "Name",
}]
I would suggest you re-write it into leveraging the ItemFileReadStore. The Store is a data container in which you can pull out items by their id. This means that your json needs to be changed slightly with description of what is identifier and - if any - which is the children attribute keys.
JSON:
{
identifier: 'itemId',
// you dont seem to have child references any but these are defaults
childrenAttrs: ['items', 'children'],
items: [
{
itemId: 1234,
name: 'Name'
}, {
...
}
]
}
then in your code, instead of using .xhr use .fetch in a store like so:
// 1.7+ syntax, pulling in dependencies.
// We want accordion and some other display widget like contentpane.
// Also we await domReady before calling our function
require(["dojo/data/ItemFileReadStore", "dijit/layout/AccordionContainer", "dijit/layout/ContentPane", "dojo/domReady!"], function(itemStore, accordion, contenpane) {
// this section is called when loading of itemstore dependencies are done
// create store
var store = new itemStore({
url:"json/"file_Name".json"
});
// create container
var acc = new accordion({style:"height: 300px"}, 'someDomNodeId');
// call XHR via .fetch and assign onComplete (opposed to 'load') callback
store.fetch({ onComplete: function(items) {
// items is an array of all the objects kept in jsonObject.items array
items.forEach(function(item) {
acc.addChild(new contentpane({
title: "Name for id: " + store.getValue(item, 'itemId'),
content: store.getValue(item, 'name')
}));
});
console.log(acc.getChildren()); // << would print out an array of contentpane widgets
});
});
This is howto :)
At any given time you could use the store and fetch some items, lets say you want to filter out some specific ones, call .query like so: store.fetch({query: { name: '*foo'/*all item.name ending with foo*/ }, onComplete: function(items) { /*cb func*/});
See
http://livedocs.dojotoolkit.org/dijit/layout/AccordionContainer#programmatic-example
and
http://livedocs.dojotoolkit.org/dojo/data/ItemFileReadStore