Coder Social home page Coder Social logo

ember-objects-web-0915's Introduction

Ember Objects

While you may never have to write your own Ember Object, you should know how they work since everything you'll be working with inherits from it.

Ember Models Models Inherit from Ember.Object Ember Controllers Controllers Inherit from Ember.Object Ember Services Services Inherit from Ember.Object

Because of this, knowing how to work with Ember Objects is kind of a big deal. Let's get started.

Creating Instances

Creating a new instance of a generic Ember Object is easy.

var obj = Ember.Object.create({name: "Bob"});
obj.get("name"); // "Bob"
obj.get("age"); // undefined
obj.set("age", 35);
obj.get("age"); // 35

Ember Objects expect you to interact with properties using the get and set methods. These methods allow Ember to update dependent properties, as we'll see later in the Computed Properties section.

Ember Objects are like JavaScript objects, in that they are open. You can add any property to an object, no need to define setters.

What if we don't want a generic object? What if we want to design an object with functions and properties? Enter the extend method.

var Person = Ember.Object.extend({
  name: null,
  greet: function(){
    return `${this.get("name")} says "Hi!"`;
  }
});

var bob = Person.create({name: "Bob", age: 35});
bob.greet(); // Bob says "Hi!"

Here we create a Person Object. We can pass create properties, even if they're not defined in the prototype. It's a good idea to set the expected properties to null to let users of your Object know what it expects. It's not required though.

In the tests you will see your classes imported like this:

export default Ember.Object.extend();

This is the same as saying:

var MyObject = Ember.Object.extend();
export default MyObject;

It's a shortcut.

Computed Properties

Computed properties are a super power in Ember and the fact that they're in EVERY OBJECT should get you excited. A computed property is a property that gets updated as your object changes. You define a list of properties you depend on, and when one of those properties changes (meaning someone called set on it), your computed property will also change. It's lazy so it won't regenerate the value every time, only when there's a change. Here's a simple example.

Let's say we want to have the total price of an item update based on the price ร— the quantity. In regular javascript you might define a function called total that will multiply price and quantity. This calculation would run every time it's called. With computed properties we only run the computation when a dependent property changes. Here's the Ember code for that:

var Item = Ember.Object.extend({
  price: 0,
  quantity: 0,
  total: Ember.computed("price", "quantity", function(){
    return this.get("price") * this.get("quantity");
  })
})

var ham  = Item.create({price: 3, quantity: 1});
ham.get("total"); // 3
ham.set("quantity", 5)
ham.get("total"); //15

Be sure to look at the created ones Ember makes for you here.

Working with collections

Ember lets you monitor changes to the properties in a collection too. Let's setup a shopping cart with items. The shopping cart will hold a series of items.

var ShoppingCart = Ember.Object.extend({
  items: [],
  total: Ember.computed("[email protected]", function(){
    return this.get("items").reduce(function(memo, item){
      return memo + item.get('total');
    }, 0);
  })
});

var Item = Ember.Object.extend({
  price: 0,
  quantity: 0,
  total: Ember.computed("price", "quantity", function(){
    return this.get("price") * this.get("quantity");
  })
});
var ham     = Item.create({price: 3, quantity: 1});
var cheese  = Item.create({price: 5, quantity: 1});
var bread   = Item.create({price: 2, quantity: 1});

var cart = ShoppingCart.create();
cart.get("total"); // 0

cart.get('items').pushObjects([ham, cheese, bread]);
cart.get("total"); // 10

This function will run only when the total property of an item is changed. We used that weird [email protected] property to say just that. Notify me when any of the item's total changes.

What if we wanted to update when an item is added or removed? Say we wanted a total number of items in the cart:

var ShoppingCart = Ember.Object.extend({
  items: [],
  total: Ember.computed("[email protected]", function(){
    return this.get("items").reduce(function(memo, item){
      return memo + item.get('total');
    }, 0);
  }),
  numberOfItems: Ember.computed("items.[]", function(){
    return this.get('items.length');
  })
});

var Item = Ember.Object.extend({
  price: 0,
  quantity: 0,
  total: Ember.computed("price", "quantity", function(){
    return this.get("price") * this.get("quantity");
  })
});
var ham     = Item.create({price: 3, quantity: 1});
var cheese  = Item.create({price: 5, quantity: 1});
var bread   = Item.create({price: 2, quantity: 1});
var cart = ShoppingCart.create();
cart.get("numberOfItems"); // 0

cart.get('items').pushObjects([ham, cheese, bread]);
cart.get("numberOfItems"); // 3

Here we did 2 things. One is the use of items.[]. This means update the computed property if the number of elements changes. You won't be notified of changes to properties. The other thing we did is return this.get('items.length'). Ember lets you chain messages inside of gets and setss.

You can use a short hand for this though, by using one of Ember's built in computed properties. Basically what we're doing is creating an alias for items.length that updates. Instead of the function we have for numberOfItems, we can have this instead:

var ShoppingCart = Ember.Object.extend({
  items: [],
  total: Ember.computed("[email protected]", function(){
    return this.get("items").reduce(function(memo, item){
      return memo + item.get('total');
    }, 0);
  }),
  numberOfItems: Ember.computed.alias("items.length")
});

var Item = Ember.Object.extend({
  price: 0,
  quantity: 0,
  total: Ember.computed("price", "quantity", function(){
    return this.get("price") * this.get("quantity");
  })
});
var ham     = Item.create({price: 3, quantity: 1});
var cheese  = Item.create({price: 5, quantity: 1});
var bread   = Item.create({price: 2, quantity: 1});
var cart = ShoppingCart.create();
cart.get("numberOfItems"); // 0

cart.get('items').pushObjects([ham, cheese, bread]);
cart.get("numberOfItems"); // 3

So nice!

ember-objects-web-0915's People

Contributors

ember-tomster avatar octosteve avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.