How can I give an empty array to Handlebars/Mustache partial? - javascript

I have a problem with partials in Handlebars.js.
This is my template and a reuseable partial for it:
Handlebars.registerPartial("children", "{{#child}}[{{age}}]{{/child}}");
var children = Handlebars.compile("{{name}} -> {{>children}}");
And here is my first data:
children({
"name": "Alice",
"child": [{
"age": 6
}, {
"age": 11
}]
});
This leads to the expected and correct output:
Alice -> [6][11]
But when I use the following data with an empty array:
children({
"name": "Bob",
"child": []
});
With this data I will get the error message:
Error: You must pass a string or Handlebars AST to Handlebars.compile. You passed function (context, options) {if (!compiled) { compiled = compileInput(); } return compiled.call(this, context, options); }
But I expected the output "Bob ->"...
When I don't use the partial doing like this, everything works fine:
var children = Handlebars.compile("{{name}} -> {{#child}}[{{age}}]{{/child}}");
But I really want to do it with the partial due to reusability. Why can't I give an empty array to this partial?
Thanks!

Related

Editing JSON files in NodeJS and DiscordJS

Right, so I am trying to wrap my head around editing (appending data) to a JSON file.
The file (users.json) looks like this:
{
"users": {
"id": "0123456789",
"name": "GeirAndersen"
}
}
Now I want to add users to this file, and retain the formatting, which is where I can't seem to get going. I have spent numerous hours now trying, reading, trying again... But no matter what, I can't get the result I want.
In my .js file, I get the data from the json file like this:
const fs = require('fs').promises;
let data = await fs.readFile('./test.json', 'utf-8');
let users = JSON.parse(data);
console.log(JSON.stringify(users.users, null, 2));
This console log shows the contents like it should:
{
"id": "0123456789",
"name": "GeirAndersen"
}
Just to test, I have defined a new user directly in the code, like this:
let newUser = {
"id": '852852852',
"name": 'GeirTrippleAlt'
};
console.log(JSON.stringify(newUser, null, 2));
This console log also shows the data like this:
{
"id": "852852852",
"name": "GeirTrippleAlt"
}
All nice and good this far, BUT now I want to join this last one to users.users and I just can't figure out how to do this correctly. I have tried so many version and iterations, I can't remember them all.
Last tried:
users.users += newUser;
users.users = JSON.parse(JSON.stringify(users.users, null, 2));
console.log(JSON.parse(JSON.stringify(users.users, null, 2)));
console.log(users.users);
Both those console logs the same thing:
[object Object][object Object]
What I want to achieve is: I want to end up with:
{
"users": {
"id": "0123456789",
"name": "GeirAndersen"
},
{
"id": "852852852",
"name": "GeirTrippleAlt"
}
}
When I get this far, I am going to write back to the .json file, but that part isn't an issue.
That's not really a valid data structure, as you're trying to add another object to an object without giving that value a key.
I think what you're really looking for is for 'users' to be an array of users.
{
"users": [
{
"id": "0123456789",
"name": "GeirAndersen"
},
{
"id": "852852852",
"name": "GeirTrippleAlt"
}
]
}
You can easily create an array in JS and the push() new items into your array. You JSON.stringify() that with no issue.
const myValue = {
users: []
};
const newUser = {
'id': '0123456789',
'name': "GeirAndersen'
};
myValue.users.push(newUser);
const strigified = JSON.stringify(myValue);

Update JSON with jquery error

I'm trying to update a JSON file with the value of a textarea using jquery push. I'm receiving the following error: " JavaScript runtime error: Unable to get property 'push' of undefined or null reference"
My jquery:
function submittedMsg(ctx) {
var id = $('.msg-input form').attr('id');
var newMsg = $('.msg-input textarea').val();
var url = "/ajax.aspx?vtl=ajax-conversation-json&cv=" + id;
$.getJSON(url, function (messageString, message) {
var message = [];
message.push({
msgcontent: newMsg,
sendname: sendRname,
mbrhref: mbrUrl,
datetime: ""
});
});
}
My JSON:
{
"messageString" :
[
{ "subject": "hello",
"msgstring": "5",
"unread": "1",
"datetime": "Oct 1 2013 9:59PM",
"orderid": "17",
"recipient": [
{
"mbrname": "Jane Doe",
"mbrhref": "/profile.aspx?mem=1227"
},
{
"mbrname": "John Smith",
"mbrhref": "/profile.aspx?mem=1337"
}
],
"message": [
{
"datetime":"2013-10-01T21:59:33.063",
"sendname":"Jane Doe",
"mbrhref":"/profile.aspx?mem=1227",
"msgcontent": "<p>Hi. I would like to talk with you about Dwarf Beryl Beauty</p>"
},
{
"datetime":"2013-11-26T16:29:17.037",
"sendname":"John Smith",
"mbrhref":"/profile.aspx?mem=1337",
"msgcontent": "Tough luck."
}
]
}
]
}
I don't necessarily need to use push to update the JSON file if there is a better way, I'm open to suggestions. I've verified my URL path is correct. Am I just missing something obvious? I'm new to JSON and only have passable jquery skills. Help!
Thanks in advance for any direction.
Try to use:
data.message.push
instead of:
data.messageString.message.push
Ah I see the issue, you have a local var and parameter of the same name message:
$.getJSON(url, function (messageString, message) { //here is param message
var message = []; //here is a local var parameter
message.push({ //this is probably referencing the parameter which is not an array or object that supports .push
Instead:
$.getJSON(url, function (data) { //I renamed the param to be more consistent with documentation, although it doesn't really matter, just will generate confusion
data.messageString.push({ //modify the json we were passed in the data param

How to access JSON property values in handlebars template

I'm creating a view in an Ember.js App and want to display some values from a JSON object. In my route's model hook, I'm calling an API endpoint that returns the JSON object which contains two arrays.
I thought I'd be able to simply reference the JSON properties in my handlebars template and it'd output the value, but that isn't working as expected. Instead, it looks like I'm getting a string description of the JSON object:
[object Object],[object Object]
How can I access the JSON object's property values in my handlebars template?
route:
var CompareRoute = Ember.Route.extend({
model: function(params) {
return $.getJSON('/api/compare_segments?' + params.ids).then(function(payload) {
return payload;
});
},
});
export default CompareRoute;
Handlebars template:
{{item_summaries}}
Example of JSON formatted returned from API endpoint (truncated):
{
"item_summaries": [
{
"item_desc": "example",
"item_id": 1,
"item_summary": [
{
"children": [
{
"measure": "% users clicking",
"value": null
}
...
{
"item_desc": "example2",
"item_id": 2,
"item_summary": [
{
"children": [
{
"children": [
...
}
you should use the each helper because you have a collection which needs to be printed out.
{{#each item_summaries}}
//access the properties of a single item_summary and write your html code
{{/each}}

How to manipulate JSON object to remove root key within Javascript?

I have a json url that returns data in the format
{
"photos" : [
{
"id": 1, "image":"https://path/to/my/image/1.jpg"
},
{
"id": 2, "image":"https://path/to/my/image/2.jpg"
}
]
}
I'm using the json in a javascript function, and need to manipulate it to remove the root key. i.e. I want something that looks like
[
{
"id": 1, "image":"https://path/to/my/image/1.jpg"
},
{
"id": 2, "image":"https://path/to/my/image/2.jpg"
}
]
I've been hacking around with various approaches, and have referred to several similar posts on SO, but nothing seems to work. The following seems like it should.
var url = 'http://path/to/my/json/feed.json';
var jsonSource = $.getJSON( url );
var jsonParsed = $.parseJSON(jsonSource);
var jsonFeed = jsonParsed.photos
What am I doing wrong?
A couple of issues there.
That's invalid JSON, in two different ways. A) The : after "photos" means that it's a property initializer, but it's inside an array ([...]) when it should be inside an object ({...}). B) There are extra " characters in front of the images keys. So the first thing is to fix that.
You're trying to use the return value of $.getJSON as though it were a string containing the JSON text. But $.getJSON returns a jqXHR object. You need to give it a success callback. That callback will be called with an object graph, the JSON is automatically parsed for you.
Assuming the JSON is fixed to look like this:
{
"photos": [
{
"id": 1,
"image": "https://path/to/my/image/1.jpg"
},
{
"id": 2,
"image": "https://path/to/my/image/2.jpg"
}
]
}
Then:
$.getJSON(url, function(data) {
var photos = data.photos;
// `photos` now refers to the array of photos
});

Ember-Data: How do "mappings" work

I'm currently trying to put something together with ember + emberdata + router + asp.net web api. Most of it seem to work, however I stuck in an error message I get when ember-data tries to findAll through the adapter for my models.
In my backend I have a model like this (C#):
public class Genre {
[Key]
public int Id { get; set; }
[Required]
[StringLength(50, MinimumLength=3)]
public string Name { get; set; }
}
Which in my app I represent it like this using ember-data:
App.Genre = DS.Model.extend({
id: DS.attr("number"),
name: DS.attr("string")
}).reopenClass({
url: 'api/genre'
});
I have also a Store defined in my App using the RESTAdapter like so:
App.store = DS.Store.create({
revision: 4,
adapter: DS.RESTAdapter.create({
bulkCommit: false
})
});
And the store is used in my controller as below:
App.GenreController = Ember.ArrayController.extend({
content: App.store.findAll(App.Genre),
selectedGenre: null
});
The router is defined as
App.router = Em.Router.create({
enableLogging: true,
location: 'hash',
root: Ember.Route.extend({
//...
genre: Em.Route.extend({
route: '/genre',
index: Ember.Route.extend({
connectOutlets: function (router, context) {
router.get('applicationController').connectOutlet('genre');
}
})
}),
//...
})
})
When I run my application, I get the following message for every object that has this same structure:
Uncaught Error: assertion failed: Your server returned a hash with the
key 0 but you have no mappings
For reference, here's the json the service is returning:
[
{
"id": 1,
"name": "Action"
},
{
"id": 2,
"name": "Drama"
},
{
"id": 3,
"name": "Comedy"
},
{
"id": 4,
"name": "Romance"
}
]
I cannot tell exactly what the problem is and since the assertion is mentioning that I need mapping, I'd like to know:
What this mapping is and how to use it.
Since the returned json is an array, should I be using a different type of controller in my app ,or is there anything I should know about when working with this type of json in ember-data? or should I change the JsonFormatter options in the server?
Any help is welcome.
I can definitely add more information if you feel this isn't enough to understand the problem.
EDIT: I've changed a few things in my backend and now my findAll() equivalent action in the server serializes the the output as the following json:
{
"genres": [
{ "id": 1, "name": "Action" },
{ "id": 2, "name": "Drama" },
{ "id": 3, "name": "Comedy" },
{ "id": 4, "name": "Romance" }
]
}
But I still can't get it to populate my models in the client and my error message has changed to this:
Uncaught Error: assertion failed: Your server returned a hash with the
key genres but you have no mappings
Not sure what else I might be doing wrong.
The method that throws this exception is sideload and checks for the mappings like this:
sideload: function (store, type, json, root) {
var sideloadedType, mappings, loaded = {};
loaded[root] = true;
for (var prop in json) {
if (!json.hasOwnProperty(prop)) { continue; }
if (prop === root) { continue; }
sideloadedType = type.typeForAssociation(prop);
if (!sideloadedType) {
mappings = get(this, 'mappings');
Ember.assert("Your server returned a hash with the key " + prop + " but you have no mappings", !!mappings);
//...
This call sideloadedType = type.typeForAssociation(prop); returns undefined and then I get the error message. The method typeForAssociation() checks for the for 'associationsByName' key which returns an empty Ember.Map.
Still no solution for this at the moment.
By the way...
My action is now like this:
// GET api/genres
public object GetGenres() {
return new { genres = context.Genres.AsQueryable() };
}
// GET api/genres
//[Queryable]
//public IQueryable<Genre> GetGenres()
//{
// return context.Genres.AsQueryable();
//}
I had to remove the original implementation which gets serialized by json.NET as I could not find config options to produce a json output as Ember-Data expects ( as in {resource_name : [json, json,...]}). Side effect of this is that I've lost built-in OData support, but I'd like to keep it. Does anyone know how could I configure it to produce different json for a collection?
The mapping can be defined in the DS.RESTAdapter. I think you could try to define something like this:
App.Store = DS.Store.extend({
adapter: DS.RESTAdapter.create({
bulkCommit: true,
mappings: {
genres: App.Genre
},
// you can also define plurals, if there is a unregular plural
// usually, RESTAdapter simply add a 's' for plurals.
// for example at work we have to define something like this
plurals: {
business_process: 'business_processes'
//else it tries to fetch business_processs
}
}),
revision: 4
});
Hope this resolves your problem.
Update:
At this time, this is not well documented, I don't remember if we found it by ourself reading the code, or perhaps Tom Dale pointed on it.
Anyway, here is the point for plurals
For the mappings, I think we were driven by the same error as you, and either we tried, either Tom teached us about this.
The RESTAdapter expects the returned JSON to be of the form:
{
"genres": [{
"id": 1,
"name": "action"
},{
"id": 2,
"name": "Drama"
}]
}
The tests are a good source of documentation, see https://github.com/emberjs/data/blob/master/packages/ember-data/tests/unit/rest_adapter_test.js#L315-329
I'm using Ember Data rev. 11 and it seems that the plurals config in DS.RESTAdapter.create never works. I looked into the codes and found a solution as following:
App.Adapter = DS.RESTAdapter.extend({
bulkCommit: false
})
App.Adapter.configure('plurals', {
series: 'series'
})

Categories