Ember Data: Get a Model in the Console - javascript

I have the simplest possible Ember app in this JSBin. All I'm trying to do is find a model. Based on other SO questions, I've tried the following.
App.User.get('store').find('user', 1);
App.User.Store.find('user', 1);
I've defined App.Store, but App.Store returns undefined in the console. I'm obviously missing the absolute most basic concepts of Ember models. Explain like I'm 5, please? I literally just want to return a user object and call a property on it.

The store is injected to routes/controllers. Inside a route/controller you can use this.store.find('user', 1) to fetch a model. But there is no global access to the store.
http://jsbin.com/aYIkAcUk/6/edit
If you feel guilty about touching the innards, which you should a bit, do not read on.
For transparency sake, you can get the store globally. After the application has initialized and is ready you can use the innards of ember to fetch it using the container lookup method. (If you need to know when the app is ready you can use the application ready hook.
var store = App.__container__.lookup('store:main');
var user = store.find('user', 1);
http://jsbin.com/aYIkAcUk/7/edit

As of Ember Data 2, the data store is now handled as a service. Thus, to look it up globally, the statement is now:
App.__container__.lookup('service:store')
Where App is the name of your Ember application. Kingpin2k's answer will not work with Ember Data 2.

Related

Service get object null after init

I have a service which stores certain object to share it between different controller. In this case I have the following code
$rootScope.$on('controller.event', function(event, arg){
self.backendConnectorService.getBackendObject('99901').then(function(object){
if(object) {
self.myService.selectDeselectObject(object);
console.log(self.myService.getCurrentObject());
$state.go('myApp.mainArea.appsArea.objects.wizards');
}
});
When I have my object I go to that state that will need the object initialized. The problem is that when I load the controller for that state, when I do self.myService.getCurrentObject() returns null. When I execute the console.log in the above code I'm getting the correct object. Why is this? I thought that services were singletons.
If you're trying to preserve data between states, you need to think in terms of using the built-in angular router or the 3rd party UI-Router (very popular, which I prefer). Then you can use resolves to resolve injections, or params to pass data along from one 'state' to another.
You're getting your 'object' then moving state - this initiates another controller, losing your object. Look at scotch.io's angular router page, which is quite helpful. You'd be better off using resolves in the state.config.js, then injecting it into your controller to use.

Firebase child() vs. Angularfire $firebaseObject

I am trying to understand WHEN Firebase actually loads the data to the client vs. doing "lazy load" (only download the data when it's needed). The reason is that I am saving images (base64) in Firebase (please don't ask why as it's only few hundred MBs). So there are two choices:
// With typical Firebase
var imagesRef = Ref.child('images');
// With Angularfire
var imagesObj = $firebaseObject(Ref.child('images'));
Ref is just a reference to my Firebase URL.
I know with Angularfire, there is $loaded() which makes me think Angularfire actually loads all the data AT ONCE and makes it available when you call $firebaseObject() right away. Is it correct?
As for using child(), I don't see any load() event to catch based on the documentation. Maybe I missed it. But does it load all data from the server to client?
If I have like 500MB of images, I definitely don't want this load-all-at-once happening.
firebase retrieve the data when you call .on on a ref
As not widely know, all the data are retrieved in one piece (wether you call .on 'value' or .on 'child_added'), so you better paginate your result using orderByFirst / Last, or using firebase util
What angular fire does when you instanciate a firebaseObject / array is calling on 'value' / 'child_added' from within the constructor function of the instance, so yes , the data are retrieved almost instantly (but in a defer hence the $loaded() function).
Check out the source code of the Object manager and the constructor of $firebaseObject for instance, it's pretty clear

Ember js access different model data from template

Im using the sane stack with mongo db. I'm fairly new to emberjs. I'm using ember 0.2.5 and sails 0.11.0 and mongodb.
I have a game route, controller and model that I can properly access from the game template. I also have a separate player route, controller, model, template setup that I can also access and manipulate properly.
A game has two players, and the player has a logo. Given I have the game data which contains each player id, I basically want to do get the player logo using the player id and display that in the game template.
Ive tried a few things, this is my last attempt to put that logic in the game controller.
//model/game.js
import DS from 'ember-data';
export default DS.Model.extend({
home_player: DS.attr('string'),
away_player: DS.attr('string'),
players: DS.hasMany('players'),
});
//Here's the logic of what I want to achieve
playerLogo: function(playerName){
for (player in players)
if player.name == playerName
return player.logo_url);
}
I've searched a bit I don't see an straight forward answer to this (or a solution I understand).
Thanks
Your model definition of Game has set relationship players: DS.hasMany('players') without setting { async: true }. I assume that you are familiar with the consequences and you set your backend to send game object with nested players relationship. If not, I'll get to it back later.
Assuming that your backend is sending the data properly you can do it like this:
game.get('players').findBy('id', idYouHave).get("logo_url"); # you can find by 'name' also
Remember to always use #set and #get when working with Ember/DS objects. You cannot query or set properties directly.
Ok, but if it's not a problem, but you rather defined the relationship without knowledge what async means, let's take a look. async means that Ember should fetch the related models by ids when they will be needed. Thus, all you get from backend is game object with player_ids table (e.g. player_ids: [1, 2]). These related players are not accessible initially - they still need to be fetched by ember, but only when explicitly needed. Therefore you would have to change your logic to use promises:
game.get('players').then(function(players) {
players.findBy('id', idYouHave).get("logo_url");
});
Remember though, that changing to async is a huge change that in case of big application can take some work to perform. You need to change your API too. However, it is more intuitive and more easy in maintenance than not using async. In long term, when you get a lot of related models, it has better performance.

How to get a Backbone.js Collection live only in memory (not persisted)?

Using Backbone.js, I use Collections to fetch and synchronize data between the client and a Ruby server. That works pretty fine.
Now I would like to use it also to store data in memory (in present case, it would be a collection of articles in a cart).
Is there a way to do this without persisting data on the server nor in the local storage, ie. have the Collection living only in memory?
Whenever I try to set the collection's url property to a null value, I am getting an Uncaught TypeError: Cannot call method 'create' of null. So... I guess this is not the right way to go!
If this not possible, what is the best design to have server and localStorage dealing with different classes in the same application?
In the beginning is easy, just don't use fetch() to populate the Collection and use reset() instead. Check reset() documentation.
But maybe you start having issues with Collection.create(), Model.destroy() and so on. So you have to be careful using this methods.. maybe you can use Collection.add() instead of Collection.create(), but I don't see good replacement for Model.destroy().
I think the most elegant way to solve your problem should be to rewrite the sync() method for your memory Collection and Model.
This is a very guess, written in the fine air:
// code simplified and no tested
var MemoryCollection = Backbone.Collection.extend({
sync: function( method, model, options ){
options.success.apply();
}
})
but maybe it can help you to start working in this direction.
If this is working you still have to use Collection.reset() instead of Collection.fetch().

Apply Backbone.js for multi-module Javascript Website

I am writing a module based javascript website, backed by a Mysql DB.
Each module talks with the DB through PHP.
On the UI, for simplicity, the module on the left will display all relevant rows, with edit(write) functionality. The module on the right display the data from the same DB, with write access too.
So each would affect the other in each update.
I'm told backbone would be a good framework. Then, I have read the todos example, and understand how there are item->itemList, view->viewList, etc...
But now, the question is, how do I apply it to this situation?
Which is an item, a view in this situation?
The module on the left and the module on the right are Views, each of which can be made up of other views.
Within the model don't store a reference to the view (as I've seen done in some of the examples):
this.view = view; //view being passed in as an arg
The reverse (a view storing a reference to a model) is okay. Your views should be doing most of the work, listening to and responding to model events. Thus, in the view initialize method you might:
model.bind("interesting-event", function(){
//the view updates/reacts to the model.
});
Also, never add a model to two collections (just one ever). When a model is assigned to a collection, Backbone sets a reference on the model that points to the owning collection.
Incidentally, the a-model-cannot-belong-to-two-collections issue is the reason why you don't want a model referencing its view. A model can have many views on one screen.
Backbone is perfect for your needs. Start with a very basic version of your app and keep fleshing it out. All the while keep reading about Backbone online. I read everything I could find (there's not a whole lot, not really). The key concept is simply event based programming (much like you'd use in VB or lots of other platforms). It's a lot of trial and error, but you'll make sense of it with practice.

Categories