Meteor Angular collections relations - angularjs

I'm using urigo:angular package. In my project I have two collections: posts and users. Is it possible to publish from server an object, which looks like this:
[{createdAt: 20-12-2015,
text: 'something',
user: { name: 'some name'}
},
{createdAt: 22-12-2015,
text: 'something2',
user: { name: 'some other name'}
}]
I mean insert user object to every post.
Update:
I have two collectionsL posts and users. Every post has user id. When I do something like this with publishComposite: https://github.com/Nitrooos/Forum-Steganum/blob/posts/server/posts.methods.coffee then I have on the client side (https://github.com/Nitrooos/Forum-Steganum/blob/posts/client/posts/posts.controller.coffee) only an array with posts, without the user in it.
I have this:
[{createdAt: 20-12-2015,
text: 'something',
userId: 123
},
{createdAt: 22-12-2015,
text: 'something2',
userId: 123
}]
So, when I'll want display a username, I'll have to do a request to every post about user?

Related

Pushing an array of objects into Firebase Collection Angular 8

I am trying to add a document into an array studyList in my users collection.
So i have a collection users where i have name, etc.. and studyList.
When i click on a button buy into a DocumentItemComponent i want to add that document into this studyList array.
My code works partially because it adds the document into the array but when i click on another document it changes the first one, it doesn't add another document.
This is my code for the adding function:
addToStudyList(user) {
const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.id}`);
const data: UserInterface = {
studyList: [{
title: this.document.title,
language: this.document.language,
description: this.document.description,
cover: this.document.cover,
category: this.document.category,
field: this.document.field,
id: this.document.id,
author: this.document.userUid,
urlDocument: this.document.urlDocument
}]
}
return userRef.set(data, {merge: true});
}
Can you help me, please?
Thank you! Have a good day!
There is no direct way to update an array inside a document, but if you are using Firestore, it provides arrayUnion and arrayRemove functions which you can use for adding/removing unique items in the array.
From firestore documentation https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array :
Try this:
userRef.update({
studyList: firebase.firestore.FieldValue.arrayUnion(data)
});
This is because when you declare:
studyList: [{
title: this.document.title,
language: this.document.language,
description: this.document.description,
cover: this.document.cover,
category: this.document.category,
field: this.document.field,
id: this.document.id,
author: this.document.userUid,
urlDocument: this.document.urlDocument
}]
in this piece of code you are assigning just one object to the the studyList array which overwrites the existing array, instead you should utilize the existing user studyList array and push your new object into it, something like this:
addToStudyList(user) {
const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.id}`);
user.studyList.push({
title: this.document.title,
language: this.document.language,
description: this.document.description,
cover: this.document.cover,
category: this.document.category,
field: this.document.field,
id: this.document.id,
author: this.document.userUid,
urlDocument: this.document.urlDocument
});
const data: UserInterface = {
studyList: user.studyList
}
return userRef.update(data);
}

Proper redux store shape

What is the recommended way to handle this sort of store in redux? I can see a couple different options but am looking to evaluate the tradeoffs of each and see what is the more idiomatic approach.
These are the base models, think of a blog:
Post
Author
Comment
Let's say I have these pages:
View a paginated list of posts: /posts
View one post: /posts/:id
View author profile: /authors/:id
When I go to Page 1 I will fetch a list of posts from the server, ultimately, when I get this data from the server, and the reducers handle it, the store will look like this:
{
posts: {
byId: {
'post-id-1': {
title: 'Post 1', authorId: 'author-id-1'
},
'post-id-2': {
title: 'Post 2', authorId: 'author-id-2'
},
allIds: ['post-id-1', 'post-id-2']
},
authors: {
byId: {
'author-id-1': {
name: 'Author 1'
},
'author-id-2': {
name: 'Author 2'
},
allIds: ['author-id-1', 'author-id-2']
}
}
Now I can render the post title with the author's name. Now when a user clicks on a specific post they are going to go to Page 2 (/posts/:id). When they do this, how should this be handled:
Option 1 Reset the store posts when they leave the page, so the store "posts" and "authors" will be empty, and when Page 2 componentDidMount() fires then make another network request to download the post content + the author details for only that one post. If so, now the store will look like:
// when the user navigates away from `/posts`
{
posts: { byId: {}, allIds: []}
authors: { byId: {}, allIds: []}
}
// when the user loads `/posts/:id`
{
posts: {
byId: {
'post-id-1': {
title: 'Post 1', authorId: 'author-id-1'
},
allIds: ['post-id-1']
},
authors: {
byId: {
'author-id-1': {
name: 'Author 1'
}
allIds: ['author-id-1']
}
}
Option 2 Alternatively, should I keep the data in the store that I already have and do something like this:
// when componentDidLoad() for `/posts/1`
componentDidMount () {
// check the `store` to see if we already have this post loaded
// if we do, then do nothing
// if we do not, then fetch it from the server
if (this.props.getPostForId(1)) {
} else {
this.props.fetchPost({postId: 1})
}
}
Next, if the user clicks into an author's profile page /authors/1, and I want to fetch the posts that author has written. How does this make my store look? Following Option 1, I can clear out the posts store again before the user navigates, and then on the author's page I can fetch all the posts that author wrote so I can render them on the author's page. But if I do not clear out the full list of posts, and now I fetch the posts that only this author wrote (post 3, post 4, post 5, post 6, etc.), so I keep the posts I already have in the store and merge the results?
{
posts: {
'post-id-1': {
title: 'Post 1', authorId: 'author-id-1'
},
'post-id-2': {
title: 'Post 2', authorId: 'author-id-2'
},
'post-id-3': {
title: 'Post 3', authorId: 'author-id-1'
},
'post-id-4': {
title: 'Post 4', authorId: 'author-id-1'
},
},
authors: {
byId: {
'author-id-1': {
name: 'Author 1'
},
'author-id-2': {
name: 'Author 2'
},
allIds: ['author-id-1', 'author-id-2']
}
}
My main confusion is around how data in the store is shared between pages (components).
When loading one page, how do I know if I already have the data in the store that I need, or if I need to make a request to get it?
When do I clear out old data from the store? Do I ever do this? Should every component be responsible for both dispatching an action to load the data that it needs on mount? And also dispatching an action to remove that data on un-mount?

backbonejs - fetching multiple model

i'm novice in backbonejs and i'm doing some project that includes fetching and displaying friends list. for this project i'm using parse.com as database. but i'm stocked at this point.
for example: i have following data's in user and friends models.
var user = [
{
id: 'x1',
firstname: 'Ashik',
lastname: 'shrestha',
phone: '12321321',
mobile: '123213',
email: 'xyz#gmail.com'
},
{
id: 'x2',
firstname: 'rokesh',
lastname: 'shrestha',
phone: '12321321',
mobile: '123213',
email: 'rokesh#gmail.com'
},
];
var friends = [
{
user_id: 'x1',
user_friend_id: 'x2'
},
{
user_id: 'x1',
user_friend_id: 'x4'
},
{
user_id: 'x1',
user_friend_id: 'x10'
},
{
user_id: 'x2',
user_friend_id: 'x25'
}
];
// collections
var userCollection = Backbone.collection.extend({
model: user
});
var friendListCollection = Backbone.collection.extend({
model: friends
});
var friends = new friendListCollection();
now what i want?
when i fetch friends collection object, i want to get friends list of user with their details.
example::
friends.fetch({
success: function(ob){
var ob =ob.toJSON();
// i want ob to be like
[
{
id: 'x2',
firstname: 'rokesh',
lastname: 'shrestha',
phone: '12321321',
mobile: '123213',
email: 'rokesh#gmail.com'
},
{
id: 'x4',
firstname: 'rokesh',
lastname: 'shrestha',
phone: '12321321',
mobile: '123213',
email: 'rokesh#gmail.com'
},
{
id: 'xx10',
firstname: 'rokesh',
lastname: 'shrestha',
phone: '12321321',
mobile: '123213',
email: 'rokesh#gmail.com'
},
]
}
});
should i create new collection to relate them or is there any other way to do this??
Thanks in advance!
To use the least of server requests to gain a better performance and less presure on server side, I would suggest you to add this logic on your server-side rather than here on client-side. e.g. When fetching with parameters like ?detail=true, the server then return simple information with detailed data, otherwise only return simple information.
If you have a good reason to seperate them into different Collections, you have to fetch those collections consequently.
Assuming you do not wish to change your data structure, you can use BackboneJS' model's idAttribute property, to retrieve a specific model from a collection by a specific key, usually an "id".
When you define your model, you should also define the idAttribute for the model, which will later allows your to access it from the collection, by the value of this field.
When a Backbone collection is synced, all models are parsed according to their defined structure, adding administrative functionality on top of their data.
Consider the following example:
var myModel = Backbone.Model.extend({
idAttribute: "id"
...
});
var myCollection = Backbone.Collection.extend({
model: myModel
...
});
Once myCollection holds one or more "myModel"(s) you can then simply use the following:
var myModelFromMyCollection = myCollection.get(id);
the idAttribute of the model can by any of the model's fields...
For your use case, lets assume both friendListCollection and userCollection are already available and have models in them, consider the following code to get the full details of each friend from it's user model like so:
friendListCollection.each(function(friendModel) {
var friendFullDetailsFromUsersCollection = userCollection.get(friendModel.id);
console.log(friendFullDetailsFromUsersCollection);
...
});

sencha touch routing extraparams kitchensink

I am trying to extend the routing in the Sencha Touch Kitchensink app as follows:
My data (in List store) are as follows:
{ category: 'fruit', str: 'tomato'},
{ category: 'fruit', str: 'green bean'},
{ category: 'vegetable', str: 'celery'},
{ category: 'vegetable', str: 'sprouts'},
{ category: 'notAVegetable', str: 'ketchup'},
{ category: 'notAVegetable', str: 'prune'}
I would like to show only those data selected by a particular category, such as "fruit"
In the Main.js controller, I am trying to do this by grabbing another parameter from the "List" node in the Demos TreeStore
routes: {
'demo/:id/:category': 'showViewById',
'menu/:id': 'showMenuById'
},
Where the showViewById action adds the extra parameter for use later
showViewById: function (id, category) {
var nav = this.getNav(),
view = nav.getStore().getNodeById(id);
console.log('view ' + id);
this.showView(view);
this.setCurrentDemo(view);
this.hideSheets();
// do stuff with category
},
I am trying to add and access 'category' as an extraParameter in my Demos.js store in the "List" tree node as follows:
{
text: 'List',
leaf: true,
id: 'list',
extraParams: {
category: 'fruit'
}
},
A few questions: Can I use an extraParameter to add this attribute to the Store? If so, how can I access it to use for my routing? I thought it would be available as metadata for my Demos store, but have not been able to access it.
Any alternatives short of creating multiple stores (one for "fruit", "vegetable", "notAVegetable," etc.) with filters on them to achieve the same thing?
TIA!

Backbone-relational between two models

By using Backbone-relational I would like to have the model task in this way:
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: userModel
};
I did try this way (1) but the result is the following (2).
Any ideas?
(1)
var User = Backbone.RelationalModel.extend({
// urlRoot
});
var Task = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasOne,
key: 'user',
relatedModel: User
}
],
// urlRoot
});
(2)
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: null // null instead of having something related to user model
};
Not sure what your the exact JSON is for your Task model, so I'm guessing here.
Backbone-relational is expecting either a fully nested model:
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: {
name: 'Fred Rogers',
id: 42,
occupation: 'Hero'
}
};
Or a string/number, which it will assume to be the id of the related model:
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: 42
};
I'm guessing you're hitting the second case, based on the null value you're getting for the user model.
When backbone-relational instantiates an instance of a model, and the related model is a "key" string/number, it will search its internal store of models to try to find a matching model. If it finds it, it sets that model as the value for the user property.
If it cannot find the model, it stashes the key in the model's relevant relation property model._relations[n].keyContents, and sets the user value to null.
It is at this point that you would use the fetchRelated function to get the related model from the datastore/API.
So, try calling task.fetchRelated() to get the related user model:
task.fetchRelated('user');

Resources