Trouble with one-to-many relationship in ember.js - javascript

I'm brand new to ember. I get the basic concepts of the framework and the naming conventions, etc. I'm trying to learn how to do relationship modeling and the docs aren't helping out too much. For the example, I'm building a simple blog app with comments (just a proof-of-concept for myself). I want to display the comments on each post page; however, I'm getting a strange error when I try to render the comments in an {{each}} block This is the relevant code (coffeescript for readability):
// file: models/post.js
BlogApp.Post = DS.Model.extend
title: DS.attr 'string'
contents: DS.attr 'string'
comments: DS.hasMany 'comment'
BlogApp.Post.FIXTURES = [
{
id: 1,
title: 'My first post',
contents: "Lorem ipsum dolor blah blah blah",
comments: [1, 3]
},
{
id: 2,
title: 'Heating up',
contents: "I'm really getting the hang of this blogging thing.",
comments: [2, 4]
}
]
Similarly for the comments:
// file: models/comment.js
BlogApp.Comment = DS.Model.extend
post: DS.belongsTo 'post'
text: DS.attr 'string'
BlogApp.Comment.FIXTURES = [
{
id: 1,
text: "Haha yes!"
},
{
id: 2,
text: "Alrighty then"
},
{
id: 3,
text: "Eh, I don't agree"
},
{
id: 4,
text: "This is great!"
}
]
The routes seem to be set up correctly.
// file: router.js
BlogApp.Router.map ->
#resource 'posts'
#resource 'post', path: 'post/:post_id', ->
#resource 'comments'
BlogApp.PostsRoute = Ember.Route.extend
model: ->
#store.find 'post'
Finally, the template (this is where the problem is occurring):
// file: templates/post/index.hbs
<h3>{{title}}</h3>
<p>{{contents}}</p>
<hr>
<h4>Comments</h4>
<ul>
{{#each comments}}
<li>hi</li>
{{/each}}
</ul>
I am getting the error Uncaught TypeError: Cannot read property 'resolve' of undefined. If I take out the each block, everything works correctly so I know it has something to do with the way the comments are being retrieved from the data store or how they are being passed by the controller.
If I take a look at the ember chrome extension, I can see the comments in the data tab, but the "text" property is undefined. Any help would be appreciated. I feel as if I have a small piece missing but I can't figure it out given my limited knowledge of ember thus far.
Thanks!

Related

Separate big array from main component to a new file

I'm new in the front end world, and I currently working on Angular project with typescript, and I created an array in order to assign to an object, so I have something like this in my TS component:
formOptions = []
ngOnInit() {
this.formOptions = [{
id: 1,
description: 'First name'
},
{
id: 2,
description: 'Middle name'
}, {
id: 3,
description: 'Last name'
}...etc
}
As you can see the array it's going to be supper big, is there a way to move the array to separate file, then import it and just assign the object? If so, where is the common path to save this path of files and what extension I should use for it?
Try storing the array in a separate .json file. Then use fetch to load the file and parse the JSON. JSON is Javascript Object Notation and it will take an array (or object) exactly as you have it laid out in your code.
[{
id: 1,
description: 'First name'
},
{
id: 2,
description: 'Middle name'
}, {
id: 3,
description: 'Last name'
}...etc
}]
The first example at MDN does exactly what I describe.

Searches for multiple terms lunrjs

According to official documentation of lunrjs:
"Searches for multiple terms are also supported. If a document matches at least one of the search terms, it will show in the results. The search terms are combined with OR".
Is there any way to achieve that only if a document matches all the search terms it will show the results?
Having these data indexed:
[
{id: 1, text: "foo", body: "jander"}
{id: 2, text: "bar", body: "clander"},
{id: 3, text: "foo bar", body: "jander crispy clander"}
{id: 4, text: "foz", body: "lorem ipsum"}
...
]
If you search by:
idx.search("foo jander clander");
I wish to have only one result ignoring the other two because they don't contain all terms but a few:
// found (1)
{id: 3, text: "foo bar", body: "jander crispy clander"}
but what I have is:
// found (3)
{id: 1, text: "foo", body: "jander"}
{id: 2, text: "bar", body: "clander"},
{id: 3, text: "foo bar", body: "jander crispy clander"}
Thanks in advance for any input.
The pull request you mentioned has been merged and released in version 2.2.0.
Lunr calls this term presence. You can't (yet) directly combine terms with a boolean operator, e.g. foo AND bar, instead you indicate the presence of term in a query. By default a term has optional presence, but it can now also be marked as required or prohibited.
The docs (guide, api) for searching have been updated, but for you specific example you would phrase the query as:
idx.search("+foo +jander +clander")
This is also exposed via the lower level query api:
idx.query(function (q) {
q.term("foo", { presence: lunr.Query.presence.REQUIRED })
q.term("jander", { presence: lunr.Query.presence.REQUIRED })
q.term("clander", { presence: lunr.Query.presence.REQUIRED })
})

Efficient algorithm / recursive function to nest items from a list

I'm currently implementing my own commenting system. Unfortunately Disqus or any other comment platform doesn't meet my requirements.
I use NodeJS and MongoDB as backend. I need to run basically two queries on my database:
Get all comments by a topic/slug
Get all comments by a user
One can comment to an topic or reply to a comment.
Hey, cool post # top lvl comment
Thanks! # reply to comment
Foo Bar! # reply to reply
and so on...
So my database schema looks like
{
id: ObjectId,
text: string,
author: { id: ObjectId, name: string },
parent: nullable ObjectId,
slug: string/number/whatever
}
If parent is null it's a top level comment, otherwise it's a reply.
Pretty easy so far, right? The problem I do have now is displaying comments below posts. When there would be only top level comments it would be easy. Just get all comments for one specific slug, sort them by date/rating/... and compile them with my HTML View Engine.
But there are in fact replies and I'm just stuck at the point where I need to organize my structure. I want to nest replies into comments within my list
Original list (simplified)
[
{ id: 1, text: 'foo', parent: null },
{ id: 2, text: 'bar', parent: 1 },
// ...
]
Expected Output
[
{ id: 1, text: 'foo', replies: [
{ id: 2, text: 'bar' },
] },
]
I've tried creating my expected output with a recursive function which got very weird tho. Unless that it wouldn't be very efficient. So since I'm really getting frustrated and kinda feeling stupid not solving this problem I've decided to ask for your help SO.
The actual problem I want to solve: How do I render my comments, that they are properly nested etc.
The question I'm going to ask: How do I organize my flat structure in an efficient way to solve the above described problem?
Here's one approach with linear complexity:
var comments = [{
id: 3,
text: 'second',
parent: 1
}, {
id: 1,
text: 'root',
parent: null
}, {
id: 2,
text: 'first',
parent: 1
}, {
id: 5,
text: 'another first',
parent: 4
}, {
id: 4,
text: 'another root',
parent: null
}];
var nodes = {};
//insert artificial root node
nodes[-1] = {
text: 'Fake root',
replies: []
};
//index nodes by their id
comments.forEach(function(item) {
if (item.parent == null) {
item.parent = -1;
}
nodes[item.id] = item;
item.replies = [];
});
//put items into parent replies
comments.forEach(function(item) {
var parent = nodes[item.parent];
parent.replies.push(item);
});
//root node replies are top level comments
console.log(nodes[-1].replies);

Display the first item in hasMany ember relationship in handlebars template

I need to display the first item in an hasMany relationship
Basically a thread could have more than 1 author but I need to display only the first one in a particular template
I've the following json
{
threads: [
{
id: 1,
authors: [2,3]
}
],
authors: [
{
id: 2,
fullname: "foo"
},
{
id: 3,
fullname: "bar"
}
]
}
And the following models
App.Thread = DS.Model.extend({
authors: DS.hasMany('author')
});
App.Author = DS.Model.extend({
fullname: DS.attr('string')
});
now in my template I'm tring to do something like {{thread.authors[0].fullname}} but it doesn't work. I've tried also thread.authors.0.fullname according to the handlebars syntax but nothing changed.
Thnx in advance for your help
Use Ember.Enumerable's firstObject:
{{thread.firstObject.fullName}}
If you are going to use it in a lot of places, its best to define it as a computed property in the model:
App.Thread = DS.Model.extend({
authors: DS.hasMany('author')
firstAuthor: Ember.computed.alias('authors.firstObject')
});
and use it in your templates as:
{{firstAuthor.name}}

Sencha Touch - HasOne Setter doesn't seem to work

So I have something along the lines of:
events: [
{
id: 1,
name: 'Birthday Party',
organiser: {
id: 1,
name: 'Jill'
},
attendees: [
{
id: 2,
name: 'Bob'
},
{
id: 3,
name: 'Jill'
}
]
}
]
As usual: Events have a name, it has attendees but I'm also looking at having one organiser.
So I've setup my HasOne proxy within the Event to HasOne Organiser and I'm trying to create the Organiser object and attach it to the Event within the console but am having no luck.
I tried something like this, as the documentation says there should be a setter created... although only seems to give example for setting an ID (which also doesn't work).
var event = Ext.create('App.model.Event', {id: 1, name: 'Birthday Party'});
event.getOrganiser(); // says undefined
event.setOrganiser({
id: 1,
name: 'Jill'
}); // says TypeError: Object #<Object> has no method 'get'
event.setOrganiser(1); // As the example but it still says the TypeError message
event.setOrganiser(Ext.create('App.model.Organiser', {
id: 1,
name: 'Jill'
}); // says TypeError: Object #<Object> has no method 'get'
So I'm confused... examples from Doc don't seem to be working for me but I need to pass in the rest of the data anyway. No idea how to approach this without spending an entire day going into the source code, dumping and breakpointing everything.
Any ideas? Should I be able to do any of the above or is it not meant to work that way? I want to POST both the Event and the Organiser object with one call... so was expecting JSON like this when I do event.save();
{
id: 1,
name: 'Birthday Party',
organiser: {
id: 1,
name: 'Jill'
}
}
Sorry if you've seen this on the ST forum but it seems to be a ghost town
Thanks for any pointers or help :)
Updated to ST 2.0.1.1 and this is what worked:
event.setOrganiser(Ext.create('App.model.Organiser', {
id: 1,
name: 'Jill'
});

Categories

Resources