Understanding Ember with a background in AngularJS


#1

Try as I might, I can’t wrap my head around Ember. I am new to MVC frameworks but Angular is easy enough that I was able to learn it quickly. If anyone has experience with both frameworks and perhaps AngularUI’s UI Router, then maybe they can help me to finally understand Ember.


1.) Behind the scenes

With Angular, I pretty much put all of my logic in factories/services. These services talk to one another via dependency injection, which is as easy as passing factoryFoo as an argument to factoryBar.

With Ember, I am not sure where to put my logic. What belongs in the route? What belongs in controllers? Where do I put my constructors, my object instances, and my general services?

2.) The “model”

There isn’t any rigid concept of a model in Angular. I can toss around data in my services and then pick and choose which data I want to show in the view.

In Ember, it seems that the model just describes a record. Records are stored on a remote server or maybe locally in localStorage. However, this record is just a simple JSON object. What if my record is actually a complicated object with properties that include arrays and functions? What if my record has a function that periodically modifies another property of that record, all while in the background?

3.) Routing

In Angular, I can use UI Router’s resolve function (or I can create my own function) in order to pick data from factories/services to pass to my controller.

Is the model hook in the route the equivalent of this? The only examples I’ve seen either retrieve records from the store or the model (['red, 'yellow', 'blue']) is explicitly typed out and returned to the hook. What if I’m not using Ember Data and my “record” exists in some other file? Is it even possible to stick a model/record in some random factory outside of Ember Data?

4.) Ember conventions and modularity

With Angular, I can organize my JavaScript in to as many or few services as I want. Any of these services can be injected into the controller.

In Ember, it seems like all my views need a controller. All of my controllers need a route. How do I create the backend network of factories that do all the dirty work? These should just be pieces of JavaScript that aren’t bound to a route/model/controller/template. Or do I somehow need to figure out how to organize all of my logic into routes and controllers?

5.) Constructors

Here is an example in Angular, which is just plain JavaScript:

function Person(first, last) {
  this.first = first;
  this.last = last;
  this.pets = [];
  this.addPet = new PetHelper({type: "dog", name: "Underdog"});
}

var john = new Person("John", "Smith);

Ember seems a bit more complicated - here is how I think it should look:

var Person = Ember.Object.extend({
  first: null,
  last: null,

  init: function () {
    this._super();
    this.set("pets", []);
    this.set("addPet", PetHelper.create({type: "dog", name: "Underdog"}));
  }
});

var john = Person.create({first: "John", last: "Smith"});

Assuming this is correct, I am now back at problem #1 - where does Ember.Object.create() go? In Angular, I would just put this in a factory. When I do ember help generate via ember-cli, I don’t see an option to generate a file to contain one-off pieces of JavaScript.

6.) Audience/project goals

My goal is to just make offline applications using web technologies. There is no server component to my applications. Any online functionality is just limited to HTTP requests using a service’s API or TCP socket/Websocket requests.

The Ember guides seem to assume that I am building something like a forum where I will be storing records on a remote server. The only persistence I need is saving things like user preferences locally. My model really shouldn’t have to use localStorage at all - if I’m using HTTP requests or Websockets, then my model/records can just exist in memory.

Is Ember the wrong framework for me if I just want to create fully offline web applications?

7.) The big picture

Angular:

Services: Most of your JavaScript will go here. You can also create your “model” here, like an array of objects. You will tell your router to iterate over this array and get a specific object, which it will pass to the controller.

Controllers: These bridge your services and templates. A controller is just a way for your services and your templates to communicate - it’s as simple as that. You can also put some template logic in your controller if you wish.

Templates: Nothing to understand here - this is just the UI. Some parts of your template will be backed by one or more controllers, that’s all you need to know.

Ember: I don’t really see the big picture in terms of all pieces of an Ember application (templates/views/controllers/routes/models/adapters/Ember Data). I know that it’s somewhat similar to Angular, but more opinionated. I mostly just don’t get what belongs in a route vs. a controller, I’m not sure what the equivalent of Angular services are.


Hopefully someone has the time to address at least a few of these concerns. I tried to keep it as short and simple as possible. There isn’t a single guide or blog post that explains Ember concepts for those who are comfortable with Angular, so hopefully this post can serve as a future reference for people like me who want to give Ember a shot but just can’t wrap their head around it.


#2

Warning: I know nothing about Angular. I’ll take a crack a few of these!

A good way to think about what-goes-where is to consider how long it’s lifetime is.

While it’s on the screen? Component. While the application is running? Service. Indefinitely? Model.

You can also loosely toss data around in Ember. The approach to models you see in the guides is from Ember Data, which is technically a separate library (albeit a great and well-integrated one). You can do your application with regular 'ole AJAX requests if you’d like and just treat them like POJOs. The advantage of modeling them with Ember data is that you can cache requests, provide a common interface in your application that is then translated for the kind of server you’re using (via an adapter), and asynchronously load related records. Functions are totally legal in Ember Data models, as are properties that are calculated off of other properties (we call them “Computed Properties”). If you you choose to model this stuff in Ember instead of POJOs, you also get all of the magic and sugar that comes with Ember objects, like bindings.

As far as being totally offline, I think you’re fine. The magic is that whether you’re storing data remotely, or just in localstorage, your application does the same this.store.find() kind of stuff. Instead of using the RESTAdapter, you would use a LocalStorageAdapter. With the caveat that I’ve never used this before, take a look at this.

The architecture stuff just changed a lot, so you’ll find a lot of references to views and controllers online that are out of date. The good news is that it’s much simpler now- controllers and views are combined into components now. So, your flow goes something like…

Router (catches URL and sends request to route) -> Route (looks up the model and applies it to a controller) -> Controller (is going away, so it just passively holds the model) -> Template (is bound to the controller, it can take our model and apply it to a component) -> Component (has all of the display logic for this route) -> Template (is bound to the component, and can use all of its properties and actions)

The controller and first template are getting deprecated very soon in favor of being about to go Route -> Component, they just couldn’t be removed in time for 2.0. Here’s a somewhat-more-official guide to this.


Climbing the learning curve of Ember -- trying an ember-calendar POC -- frustrated
#3

Thank you for giving me some things to think about. Reading over your post, I kind of feel like the gears are finally starting to turn.

It sounds like Ember services are the near equivalent of Angular factories/services. In my planned applications, I only need persistence for basic user preferences. All my my models/data in Angular exist only in memory when the application is running, so I suppose that I should look more into services.

However, it sounds like Ember Data is something that I want to take advantage of despite the fact that there will not be any remote component to my applications. It might be possible for me to rethink the structure of my Angular models - for an application using websockets where a user connects to multiple servers, each connection is represented by a new object with its own socket instance. In Ember, I guess that I could separate the socket instance from the model/record and somehow point each socket instance in the service to the correct record for updating as necessary.

This brings me back to another question that I had previously. It seems like model attributes are limited to String, Number, Boolean, and Date. Is it possible to have array and object properties, or am I supposed to use hasMany and belongsTo in order to approximate what would normally be arrays and objects in my Angular model?


#4

Awesome question! Those attributes are called “transforms”, and they’re totally optional. What they do is try to coerce data coming in/out of the store into those data types. You can define your own transforms if that might be useful for you, or you can use DS.attr() wide-open if you want to leave the data as is. Breaking up your objects into related models may be useful for you (especially if you have to build records that will be written somewhere), but you can also just use your objects/arrays as-is.

I can’t say for sure whether the service concept is the same in both frameworks, but I would imagine it is. Formerly, a service was a standalone controller that was needed into whatever controllers required it. Currently, a service is a simple Ember object that you can put whatever state or methods you want in and inject it other ember objects. In Ember-CLI, you can do that by type (“Inject this into all components”), or specific instances (“Inject this into the post and comment routes”), or declaratively in the objects themselves with inject(). For example, service injection is exactly how the store object can magically be accessed with this.store everywhere.


#5

It seems like services are similar between the two frameworks insofar as they can be used to create reusable pieces of code like constructors or general functions that aren’t rigidly tied to a specific route or component. Interestingly enough, I don’t think services are really mentioned in the Ember guides, but they seem like one of the most important parts of the application, at least in my case.

Thank you for clarifying Ember Data and models to me. I think it’s going to be an enormous challenge to restructure my Angular “model” to fit the Ember paradigm, but I will experiment with different things in hopes of finding something that works.

There are still so many concepts that I’m struggling with, including simpler things like Ember’s syntax, but at least I finally have a very vague idea of where I might be able to start with writing my application. The more I think about it, the more I get the feeling that the two frameworks are actually pretty dissimilar - one might be able to achieve the same results with either framework, but the paths taken to get there might be very different. I hope that Ember clicks with me some day because I want to take advantage of all the great things that it promises.


#6

Have patience and keep asking questions. Relative to other frameworks, Ember asks a lot more of you up front. That investment pays off so, so well though!


#7

To second what @kylecoberly said about things shifting a lot recents. Ember has pretty poor documentation in this transitionary moment, though it seems like there is work in the not to distant future that will be done to improve this (post 2.0 from the sound of it). There are a number of recent changes and best practices that are not in the guides / documentation, look to the slack channel and here to get insight. When searching on google approach anything more than a few months old with some skepticism, the solution / best practice MAY have changed since then. The Ember blog also has lots of new bits of information and even some undocumented (not in guides) features. Finally don’t be afraid to poke around the git repo and rfcs there is a lot of useful stuff there. I found the rfcs , both open and recently closed, especially helpful in understanding some of the architectural shifts that are fast approaching in 2.0.


#8

Services

Services in ember is use to share data between routes. you can also store your data there if it just need to exist in memory. it also a perfect place for functions relate to that data.

utils

utils is use to share functions across the application. it’s much easy to use, it’s just es6 modules, you can just import it in place where you need it.

model

model is use to get all the data needed for perticular route. data it self can come from anywhere. Some temporary state can store in component, and they will lost each time you leave the component.

Ember data

Ember data is mostly use to communicate with some backend, like api server or localstorage. It’s totally optional. It have some benefit, but may too complicate for some cases. It’s most useful when you have array of some data.

constructors

Ember call constructor automatic for things like route and controller. in case of customed objects, consturctors can call at any place suit for it, most likely in model hook or in service.

Ember conventions and modularity

looks like you missed ember-cli http://www.ember-cli.com/user-guide/#getting-started

offline application

i have create some offline application before, which deliver to end user by nw.js and didn’t use network at all. ember is a perfect fit. Just don’t use ember-data unless you get benefit from it. I use service to store in memory data, and add getter and setter in that service in case i need to store it to local files. Anything else is same.

The big picture

service: use to store data need to exist when application is run.

model: data provide to route. model hook is the place to retrive data and organize it.

routable controllers: use to hold some temporary state for route. they will lost after leave the route

route: hold the model hook and actions for perticular route


Climbing the learning curve of Ember -- trying an ember-calendar POC -- frustrated
#9

Very helpful answer, thanks a lot. Services and utils were the missing pieces of the puzzle when I was trying to learn Ember via the guides.

I am using ember-cli and in fact that is the only way I know how to use Ember. My question regarding modularity pertained more so to the backend network of services that handle and manipulate the application’s data, and how they talk to one another. Based on your answer, services are injected where they are needed and utils are just imported.

I feel like there should be a separate section in the guides that focuses on services and utils (unless maybe I missed it?). Just being aware that those two elements exist would probably make things less confusing for people coming from Angular.


#10

I totally agree that services and utils should get guide sections. I think the reason they haven’t is that they were added to Ember API relatively recently (1.10 for services, and I don’t think utils are even an official class), and I think they came from Ember CLI rather than Ember proper.


#11

I think the reason they haven’t is that they were added to Ember API relatively recently

That leaves me curious as to how applications were built prior to the existence of services. I’m guessing that means that logic was shoved into routes and controllers, but that would make developing certain applications extremely nasty. Now that I know about services and utils, I can’t imagine making anything in Ember without them.


#12

Before services, you made a standalone controller and used needs to inject it in another controller. There’s an entire page in the guide about it, albeit a kind of buried one. It actually worked pretty well, but the new way gives you a lot more flexibility.

It bears mentioning that there is nothing inherently magical about the service object. If you look up the API for it and remove the things it inherits from Ember.Object, there’s nothing left. I imagine it has its own class to encourage the architecture pattern and provide a place to add functionality in the future. At it’s core though, you’re just injecting plain Ember objects into other objects in your application.


#13

I have been using ember for a few months now. I’m driving full speed on Ember 2.0 which has little to no documentation yet. It has been a struggle at times, but I have to say this is one of the most useful and straightforward threads I have read yet for any new Ember devs. Especially regarding services and the short, simple plain English explanations of what or how Components, Utils, Services are used. I really wish some of this thread had been in the ember Guides. I thoroughly believe Ember would fair much batter in the “battle” with the other platforms/frameworks if the docs were drastically improved.


#14

I agree. Thanks to @kylecoberly’s and @xudaiqing’s explanations, I finally got a working prototype of my project.

The biggest issue was figuring out where things go, but they both explained that pretty well in terms of an object’s life cycle. I think the Ember guides are good but they are very dense in the sense that it takes quite a while to understand each example and how it fits in the big picture.

I think that their explanations are useful for anyone trying to learn Ember, even those without a background in Angular or another JavaScript framework. Their explanations should be consolidated into a separate beginner’s guide that users can read before they dive into the main guides (which should place more emphasis on services and utils).