From 2e59524a1539d5cc69788834df6f8e0747f04b35 Mon Sep 17 00:00:00 2001 From: Michael Kaiser-Nyman Date: Sat, 8 Aug 2015 09:29:24 -0700 Subject: [PATCH 1/7] add introduction to object model section --- data/pages.yml | 2 ++ source/object-model/index.md | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 source/object-model/index.md diff --git a/data/pages.yml b/data/pages.yml index baf1e1e06..ca229a05b 100644 --- a/data/pages.yml +++ b/data/pages.yml @@ -18,6 +18,8 @@ - title: "The Object Model" url: 'object-model' pages: + - title: "Objects in Ember" + url: "index" - title: "Classes and Instances" url: "classes-and-instances" - title: "Reopening Classes and Instances" diff --git a/source/object-model/index.md b/source/object-model/index.md new file mode 100644 index 000000000..2fe15bb1f --- /dev/null +++ b/source/object-model/index.md @@ -0,0 +1,16 @@ +You'll soon notice that standard JavaScript objects aren't used widely in Ember, +except as key-value pairs (often referred to as _hashes_). This is because +JavaScript objects don't support the ability to observe when an object changes, +which Ember needs to update data throughout an application. +Ember's object model builds on standard JavaScript objects to enable this +functionality, as well as bring several features like mixins and initialization +to make working with them a more pleasant experience. Although these features +aren't available in standard JavaScript, many of them are designed to align with +proposed additions to the ECMAScript standard. + +In addition to bringing its own object model, Ember also extends the built-in +JavaScript `Array` prototype with its Enumerable interface to enable it to +observe changes and provide more features. + +Finally, Ember extends the `String` prototype with a few [formatting and +localization methods](http://emberjs.com/api/classes/Ember.String.html). From 109f5d6ea3e9b4bb61bb2a1617787124abf62a7a Mon Sep 17 00:00:00 2001 From: Michael Kaiser-Nyman Date: Sat, 8 Aug 2015 09:29:56 -0700 Subject: [PATCH 2/7] remove stray ember view references --- source/object-model/bindings.md | 4 +--- source/object-model/classes-and-instances.md | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/source/object-model/bindings.md b/source/object-model/bindings.md index c6d6f3ac9..e3870957b 100644 --- a/source/object-model/bindings.md +++ b/source/object-model/bindings.md @@ -1,8 +1,6 @@ A binding creates a link between two properties such that when one changes, the other one is updated to the new value automatically. Bindings can connect -properties on the same object, or across two different objects. Unlike most other -frameworks that include some sort of binding implementation, bindings in -Ember.js can be used with any object, not just between views and models. +properties on the same object, or across two different objects. The easiest way to create a two-way binding is to use a computed alias, that specifies the path to another object. diff --git a/source/object-model/classes-and-instances.md b/source/object-model/classes-and-instances.md index 75d62388b..d231dfe02 100644 --- a/source/object-model/classes-and-instances.md +++ b/source/object-model/classes-and-instances.md @@ -17,10 +17,10 @@ You can also create a _subclass_ from any existing class by calling its `extend()` method. For example, you might want to create a subclass of Ember's built-in `Ember.Component` class: -```app/views/person.js -PersonView = Ember.Component.extend({ - tagName: 'li', - classNameBindings: ['isAdministrator'] +```app/components/todo-item.js +export default Ember.Component.extend({ + classNameBindings: ['isUrgent'], + isUrgent: true }); ``` From 32b419004d5f2cf8df1f8d140c5a9ae14aa5fd12 Mon Sep 17 00:00:00 2001 From: Michael Kaiser-Nyman Date: Sat, 8 Aug 2015 09:30:07 -0700 Subject: [PATCH 3/7] add introduction to classes and instances guide --- source/object-model/classes-and-instances.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/object-model/classes-and-instances.md b/source/object-model/classes-and-instances.md index d231dfe02..87f1b7809 100644 --- a/source/object-model/classes-and-instances.md +++ b/source/object-model/classes-and-instances.md @@ -1,3 +1,7 @@ +As you learn about Ember, you'll see code like `Ember.Component.extend()` and +`DS.Model.extend()`. Here, you'll learn about this `extend()` method, as well +as other major features of the Ember object model. + ### Defining Classes To define a new Ember _class_, call the `extend()` method on From cc8544d5fabd36706c5df86c31532307b3059523 Mon Sep 17 00:00:00 2001 From: Michael Kaiser-Nyman Date: Sat, 8 Aug 2015 09:37:12 -0700 Subject: [PATCH 4/7] warn against using bindings and observers on their respective pages --- data/pages.yml | 2 -- source/object-model/bindings.md | 7 ++++--- source/object-model/observers.md | 9 +++++++++ source/object-model/what-do-i-use-when.md | 21 --------------------- 4 files changed, 13 insertions(+), 26 deletions(-) delete mode 100644 source/object-model/what-do-i-use-when.md diff --git a/data/pages.yml b/data/pages.yml index ca229a05b..8cde2de2f 100644 --- a/data/pages.yml +++ b/data/pages.yml @@ -32,8 +32,6 @@ url: "observers" - title: "Bindings" url: "bindings" - - title: "Bindings, Observers, Computed Properties: What Do I Use When?" - url: "what-do-i-use-when" - title: "Enumerables" url: 'enumerables' diff --git a/source/object-model/bindings.md b/source/object-model/bindings.md index e3870957b..2b348ef9c 100644 --- a/source/object-model/bindings.md +++ b/source/object-model/bindings.md @@ -1,6 +1,7 @@ -A binding creates a link between two properties such that when one changes, the -other one is updated to the new value automatically. Bindings can connect -properties on the same object, or across two different objects. +Unlike most other frameworks that include some sort of binding implementation, +bindings in Ember.js can be used with any object. That said, bindings are most +often used within the Ember framework itself, and for most problems Ember app +developers face, computed properties are the appropriate solution. The easiest way to create a two-way binding is to use a computed alias, that specifies the path to another object. diff --git a/source/object-model/observers.md b/source/object-model/observers.md index 3a46c31d5..f7031f5a3 100644 --- a/source/object-model/observers.md +++ b/source/object-model/observers.md @@ -1,4 +1,13 @@ Ember supports observing any property, including computed properties. + +Observers should contain behavior that reacts to changes in another property. +Observers are especially useful when you need to perform some behavior after a +binding has finished synchronizing. + +Observers are often over-used by new Ember developers. Observers are used +heavily within the Ember framework itself, but for most problems Ember app +developers face, computed properties are the appropriate solution. + You can set up an observer on an object by using `Ember.observer`: ```javascript diff --git a/source/object-model/what-do-i-use-when.md b/source/object-model/what-do-i-use-when.md deleted file mode 100644 index 41d43fad3..000000000 --- a/source/object-model/what-do-i-use-when.md +++ /dev/null @@ -1,21 +0,0 @@ -Sometimes new users are confused about when to use computed properties, -bindings and observers. Here are some guidelines to help: - -1. Use *computed properties* to build a new property by synthesizing other -properties. Computed properties should not contain application behavior, and -should generally not cause any side-effects when called. Except in rare cases, -multiple calls to the same computed property should always return the same -value (unless the properties it depends on have changed, of course.) - -2. *Observers* should contain behavior that reacts to changes in another -property. Observers are especially useful when you need to perform some -behavior after a binding has finished synchronizing. - -3. *Bindings* are most often used to ensure objects in two different layers -are always in sync. For example, you bind your views to your controller using -Handlebars. - -### More Resources -Stefan Penner at Yahoo discusses when to use observers and when to use computed properties: -- [The observer tip-jar - Stefan Penner Silicon Valley Ember.js meetup Jun 15, 2015](https://www.youtube.com/watch?v=7PUX27RKCq0) - From 886a0c41395409f36c36d8825ab4928c0d0c8fc0 Mon Sep 17 00:00:00 2001 From: Michael Kaiser-Nyman Date: Sat, 8 Aug 2015 11:46:34 -0700 Subject: [PATCH 5/7] reorganize enumerable guide --- source/object-model/enumerables.md | 61 ++++++------------------------ 1 file changed, 11 insertions(+), 50 deletions(-) diff --git a/source/object-model/enumerables.md b/source/object-model/enumerables.md index 324667a01..f335d2afc 100644 --- a/source/object-model/enumerables.md +++ b/source/object-model/enumerables.md @@ -1,10 +1,10 @@ -## Enumerables - In Ember.js, an Enumerable is any object that contains a number of child objects, and which allows you to work with those children using the [Ember.Enumerable](http://emberjs.com/api/classes/Ember.Enumerable.html) API. The most common Enumerable in the majority of apps is the native JavaScript array, which -Ember.js extends to conform to the Enumerable interface. +Ember.js extends to conform to the Enumerable interface. Ember also provides +Ember.Set, a data structure that can efficiently answer whether it includes an +object. By providing a standardized interface for dealing with enumerables, Ember.js allows you to completely change the way your underlying data is @@ -16,51 +16,13 @@ possible. This minimizes incompatibility with other libraries, and allows Ember.js to use the native browser implementations in arrays where available. -For instance, all Enumerables support the standard `forEach` method: - -```javascript -[1,2,3].forEach(function(item) { - console.log(item); -}); - -//=> 1 -//=> 2 -//=> 3 -``` - -In general, Enumerable methods, like `forEach`, take an optional second -parameter, which will become the value of `this` in the callback -function: - -```javascript -var array = [1,2,3]; +## API Overview -array.forEach(function(item) { - console.log(item, this.indexOf(item)); -}, array) - -//=> 1 0 -//=> 2 1 -//=> 3 2 -``` - -### Enumerables in Ember.js - -Usually, objects that represent lists implement the Enumerable interface. Some examples: - - * **Array** - Ember extends the native JavaScript `Array` with the - Enumerable interface (unless you [disable prototype - extensions.](../../configuring-ember/disabling-prototype-extensions)) - * **Ember.Set** - A data structure that can efficiently answer whether it - includes an object. - -### API Overview - -In this guide, we'll explore some of the most common Enumerable +In the rest of this guide, we'll explore some of the most common Enumerable conveniences. For the full list, please see the [Ember.Enumerable API reference documentation.](http://emberjs.com/api/classes/Ember.Enumerable.html) -#### Iterating Over an Enumerable +### Iterating Over an Enumerable To enumerate all the values of an enumerable object, use the `forEach` method: @@ -76,7 +38,7 @@ food.forEach(function(item, index) { // Menu Item 3: Adobo Chicken ``` -#### Making an Array Copy +### Making an Array Copy You can make a native array copy of any object that implements `Ember.Enumerable` by calling the `toArray()` method: @@ -94,7 +56,7 @@ states.toArray() Note that in many enumerables, such as the `Ember.Set` used in this example, the order of the resulting array is not guaranteed. -#### First and Last Objects +### First and Last Objects All Enumerables expose `firstObject` and `lastObject` properties that you can bind to. @@ -111,7 +73,7 @@ animals.get('lastObject'); //=> "peacock" ``` -#### Map +### Map You can easily transform each item in an enumerable using the `map()` method, which creates a new array with results of calling a @@ -145,7 +107,7 @@ states.mapBy('capital'); //=> ["Honolulu", "Sacramento"] ``` -#### Filtering +### Filtering Another common task to perform on an Enumerable is to take the Enumerable as input, and return an Array after filtering it based on @@ -185,7 +147,7 @@ todos.filterBy('isDone', true); If you want to return just the first matched value, rather than an Array containing all of the matched values, you can use `find` and `findBy`, which work just like `filter` and `filterBy`, but return only one item. -#### Aggregate Information (All or Any) +### Aggregate Information (All or Any) If you want to find out whether every item in an Enumerable matches some condition, you can use the `every` method: @@ -223,4 +185,3 @@ Just like the filtering methods, the `every` and `some` methods have analogous ` people.isEvery('isHappy', true) // false people.isAny('isHappy', true) // true ``` - From ce88129d2002b7b80465dc970ae52e99b3feaf92 Mon Sep 17 00:00:00 2001 From: Michael Kaiser-Nyman Date: Sat, 8 Aug 2015 11:46:57 -0700 Subject: [PATCH 6/7] add content on observable methods to enumerable guide --- source/object-model/enumerables.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/source/object-model/enumerables.md b/source/object-model/enumerables.md index f335d2afc..943072c0d 100644 --- a/source/object-model/enumerables.md +++ b/source/object-model/enumerables.md @@ -16,6 +16,30 @@ possible. This minimizes incompatibility with other libraries, and allows Ember.js to use the native browser implementations in arrays where available. +## Use of Observable Methods + +In order for Ember to observe when you make a change to an enumerable, you need +to use special methods that Ember.Enumerable provides. For example, if you add +an element to an array using the standard JavaScript method `push`, Ember will +not be able to observe the change, but if you use the Enumerable method +`pushObject`, the change will propagate throughout your application. + +Here is a list of standard JavaScript array methods and their observable +Enumerable equivalents: + + + + + + + + + + + + +
Standard MethodObservable Equivalent
poppopObject
pushpushObject
reversereverseObjects
shiftshiftObject
unshiftunshiftObject
+ ## API Overview In the rest of this guide, we'll explore some of the most common Enumerable From d4391f23b8af2c968d1a181a31ccfb34a202de07 Mon Sep 17 00:00:00 2001 From: Michael Kaiser-Nyman Date: Sun, 9 Aug 2015 08:35:35 -0700 Subject: [PATCH 7/7] remove references to deprecated Ember.Set --- source/object-model/enumerables.md | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/source/object-model/enumerables.md b/source/object-model/enumerables.md index 943072c0d..19159a98c 100644 --- a/source/object-model/enumerables.md +++ b/source/object-model/enumerables.md @@ -2,9 +2,7 @@ In Ember.js, an Enumerable is any object that contains a number of child objects, and which allows you to work with those children using the [Ember.Enumerable](http://emberjs.com/api/classes/Ember.Enumerable.html) API. The most common Enumerable in the majority of apps is the native JavaScript array, which -Ember.js extends to conform to the Enumerable interface. Ember also provides -Ember.Set, a data structure that can efficiently answer whether it includes an -object. +Ember.js extends to conform to the Enumerable interface. By providing a standardized interface for dealing with enumerables, Ember.js allows you to completely change the way your underlying data is @@ -62,24 +60,6 @@ food.forEach(function(item, index) { // Menu Item 3: Adobo Chicken ``` -### Making an Array Copy - -You can make a native array copy of any object that implements -`Ember.Enumerable` by calling the `toArray()` method: - -```javascript -var states = Ember.Set.create(); - -states.add("Hawaii"); -states.add("California") - -states.toArray() -//=> ["Hawaii", "California"] -``` - -Note that in many enumerables, such as the `Ember.Set` used in this -example, the order of the resulting array is not guaranteed. - ### First and Last Objects All Enumerables expose `firstObject` and `lastObject` properties