Ember 2.x Ember.Object & Simple Properties
This course has been updated! We now recommend you take the Ember Octane Fundamentals course.
Transcript from the "Ember.Object & Simple Properties" Lesson
>> Mike North: So the last little mini lesson here is Ember.Object and Simple Properties. So Ember.Object is the base class of most everything. The router is an Ember.Object routes also component services, Ember data models. It's all built on this, and to get and set properties you use this.get and this.set.
[00:00:35] I'll explain why as we dive in a little deeper, but that is the mechanism.
>> Speaker 2: I find myself using that only in tests when I wanna stub something out. Are there other good use cases for actually instantiating Ember.Object?
>> Mike North: So, when I'm talking about, I understand that many people don't end up directly using Ember.Object, but an alternate title for this section might be Common Functionality You Should Be Aware of Between All of the Things We're Talking About Today.
[00:01:09] And this is, we are dealing directly with the base class, not dealing with the routeness of route. So, this is the basic idea here. We can have a property called firstName right? And in this case I am just creating an instance of an Ember.Object, assigning a property with a value at instantiation time.
[00:01:37] And then you can see that I can call .get and retrieve the value of the property.
>> Mike North: So set just is a two argument method and it's property key and new value.
>> Mike North: And last thing, actually I have couple more things here. So properties can be deeply nested in a hierarchy, and all you need to do to directly access first within name is get the property name.first.
[00:02:13] And so this allows you to be much more concise especially if what you're getting are other objects that have other properties on them. You don't have to do this .get .get .get, that can all be chained together just in terms of describing the property that you want to get.
>> Mike North: And the last thing I think you'll need to be aware of for what we're about to do is you have to treat arrays a little bit differently. And the reason is that Ember needs to be able to observe arrays. And in order to do so, we need to use the appropriate hooks for adding things and removing things.
[00:02:55] So that things that are bound to the array, things that are, like an each for example can be informed that they need to update themselves. So in this case you will want to get an array, and then operate on that array. So here you can see that I start out with a two component name.
[00:03:20] And I can print it out and prove that I can get the array and that the typical array methods that you're used to work. And then I used popObject which is a KVO-compliant method. KVO means key value observer. So that means that things that are observing this array will be notified that something has changed.
[00:03:42] And then when I attempt to print the same thing we can see that I've removed an object. Just be aware of this because you can, if you just start directly manipulating with push you may not get the updates you're expecting to get.
>> Speaker 3: So those are all the functions you'll find in the class?
>> Mike North: If you want to see in this case, in this specific example if you wanted the complete set I would look at Ember.MutableArray. Right, so there's Ember.Array which is not necessarily mutable, and then there's MutableArray which contains a variety of KVO compliant methods that you can use to manipulate.
[00:04:28] All right, so I'm just gonna free-form a little bit to illustrate how these things fit together, and this has nothing to do with the example. But I just want to flesh it out a little bit and show you some actual use before we start getting into this.
>> Mike North: So I'm gonna generate a service called authentication.
[00:04:53] And I'm gonna turn my mirroring off so I don't code like super slowly. [LAUGH] All right and pardon the swiping back and forth. So we're gonna generate a service and actually this should be fine. We already have things that can handle actions. All right, so I'm gonna go to my code and look at,
>> Mike North: Let's close all my stuff. So we've got a new folder here that wasn't there before called Services and if we look at the file, it's just giving me a nice little thing to start with. I'm gonna add an array, records.
>> Mike North: And then I'm gonna go to a route that currently isn't returning anything from its model hook.
>> Mike North: Actually we can just do this a little bit differently.
>> Mike North: So instead of controller, I'm gonna use this trick where we add something to make it available to the template. And what do we do when we set up the controller first? Super.
>> Mike North: All right, and now it's time to inject this service onto the route so that this route will have access to this shared object that has an array I'm interested in.
[00:06:35] And the way that works is.
>> Mike North: Just that. Earlier I said the name was optional. Passing a name into this function here is optional. If you don't pass a name in the property key itself will be used as the name. So this is equivalent to that, but we're going convention over configuration style.
[00:07:10] All right and now I'm just gonna just do controller set records.
>> Mike North: And we'll do,
>> Mike North: this.get('authentication.records')
>> Mike North: And I'm actually gonna put something in there just for fun.
>> Mike North: I'm gonna go into the org template and I'm gonna use a cool little debugging trick here. This is the equivalent of console.log.
[00:07:55] Keep in mind, your templates are updated dynamically. Don't expect your log to be hold over, and over, and over, and over again cuz things may not work the way you expect. So, we're gonna drill into the correct page, right? I'm in the org wrap template here. And so now I'm looking at, this means that this template will be active.
[00:08:21] In fact the word Facebook is coming from this h4 here. And I just want to point out that log records is showing up here as you know in the console. And you can look at it and see that this is in fact the property from the service.
>> Mike North: So I'm gonna each over it.
>> Mike North: As record.
>> Mike North: And we'll do another ul.
>> Mike North: All right, and so now we should get, there we go, one. So now, I want to add a span here with an action.
>> Mike North: And I'm gonna call it addTwoToRecords or better yet.
>> Mike North: All right, so this is the span.
[00:09:31] And just an interesting side note, you can see that there is some indication that an action has been bound to this span. You can see it right as a dom an attribute. So if I click it.
>> Mike North: We're gonna get an error message. And Ember is telling me that this action bubbled up and nothing handled it.
[00:10:01] And the reason is, I haven't implemented it in the route yet. So if I go to routes and I add an action here.
>> Mike North: And I add this action here and we'll call it value.
>> Mike North: Alert to start. And look, now we're receiving a click event, and in fact.
>> Mike North: We're passing along the data as well. That argument to the action is being passed along. That's what val is. And so now, to actually add this to the array you just do this.get('authentication'). And add a similar looking object.
>> Speaker 4: You gotta do records, allocation.records?
>> Mike North: You're correct, so that would have just added it directly to the service which would have been bad.
[00:11:15] And I click this, and we see Two pop up. And in fact I'm adding similar objects over and over and over again. So what this should hopefully illustrate is I can access properties using this.get. I can kind of have this object, this service here, and have that store some data and if I wanted to make this available on multiple rounds they're all sharing the same instance.
[00:11:44] It's a singleton. And then finally I set up an action binding so that my route can handle this action and do something about it. So that make sense how those things kind of fit together in what I showed you?
>> Speaker 5: How do you do an action other than the default of click?
>> Mike North: Like what?
>> Speaker 5: Like keyup or something, anything other than the default. Like resize the browser.
>> Mike North: So resize the browser is an interesting one. In that case, you'll only have a resize event on window right that's the only thing that's gonna fire that event. And that's a great example of a service where you could have one event listener for a window that is shared across anything that needs to know about resizing.
[00:12:33] Instead of having every single component that wants to try to be responsive, each independently attaching listeners. That gets quite messy and, depending on what kind of component you're using, like if the table cell sparkline, that can be very expensive. And in terms of like a hover event or something, so there are other ways to bind actions.
[00:13:01] I'd like us to start here, but I will not let that go unanswered.