Google News
logo
Ember.js Interview Questions
Creating Records : You can create records by calling the createRecord() method on the store.
store.createRecord('post', {
  title: 'Rails is Omakase',
  body: 'Lorem ipsum'
});
The store object is available in controllers and routes using this.store.
 
Updating Records : Making changes to Ember Data records is as simple as setting the attribute you want to change:
this.store.findRecord('post', 1).then(function(post) {
  // ...after the record has loaded
  post.title = 'A new post';
});
 
Deleting Records : Deleting records is as straightforward as creating records. Call deleteRecord() on any instance of Model. This flags the record as isDeleted. The deletion can then be persisted using save(). Alternatively, you can use the destroyRecord method to delete and persist at the same time.
let post = store.peekRecord('post', 1);
post.deleteRecord();
post.isDeleted; // => true
post.save(); // => DELETE to /posts/1

// OR
post = store.peekRecord('post', 2);
post.destroyRecord(); // => DELETE to /posts/2
Ember Data includes several built-in relationship types to help you define how your models relate to each other.
 
One-to-One : To declare a one-to-one relationship between two models, use belongsTo:
 
app/models/user.js :
import Model, { belongsTo } from '@ember-data/model';

export default class UserModel extends Model {
  @belongsTo('profile') profile;
}
app/models/profile.js :
import Model, { belongsTo } from '@ember-data/model';

export default class ProfileModel extends Model {
  @belongsTo('user') user;
}

One-to-Many : 
To declare a one-to-many relationship between two models, use belongsTo in combination with hasMany, like this:
 
app/models/blog-post.js
import Model, { hasMany } from '@ember-data/model';

export default class BlogPostModel extends Model {
  @hasMany('comment') comments;
}
app/models/comment.js :
import Model, { belongsTo } from '@ember-data/model';

export default class CommentModel extends Model {
  @belongsTo('blog-post') blogPost;
}

Many-to-Many : 
To declare a many-to-many relationship between two models, use hasMany:
 
app/models/blog-post.js :
import Model, { hasMany } from '@ember-data/model';

export default class BlogPostModel extends Model {
  @hasMany('tag') tags;
}
app/models/tag.js :
import Model, { hasMany } from '@ember-data/model';

export default class TagModel extends Model {
  @hasMany('blog-post') blogPosts;
}
Along with the records returned from your store, you'll likely need to handle some kind of metadata. Metadata is data that goes along with a specific model or type instead of a record.
 
Pagination is a common example of using metadata. Imagine a blog with far more posts than you can display at once. You might query it like so:
let result = this.store.query('post', {
  limit: 10,
  offset: 0
});
 
Each serializer will expect the metadata to be returned differently. For example, Ember Data's JSON deserializer looks for a meta key:
{
  "post": {
    "id": 1,
    "title": "Progressive Enhancement is Dead",
    "comments": ["1", "2"],
    "links": {
      "user": "/people/tomdale"
    },
    // ...
  },

  "meta": {
    "total": 100
  }
}
Regardless of the serializer used, this metadata is extracted from the response. You can then read it with .meta.

This can be done on the result of a store.query() call :
store.query('post').then(result => {
  let meta = result.meta;
});
On a belongsTo relationship :
let post = store.peekRecord('post', 1);

let author = await post.author;
let meta = author.meta;
Or on a hasMany relationship :
let post = store.peekRecord('post', 1);

let comments = await post.comments;
let meta = comments.meta;
After reading it, meta.total can be used to calculate how many pages of posts you'll have.
 
To use the meta data outside of the model hook, you need to return it:
 
app/routes/users.js :
import Route from '@ember/routing/route';
import { service } from '@ember/service';

export default class UsersRoute extends Route {
  @service store;

  model() {
    return this.store.query('user', {}).then((results) => {
      return {
        users: results,
        meta: results.meta
      };
    });
  }
  setupController(controller, { users, meta }) {
    super.setupController(controller, users);
    controller.meta = meta;
  }
}
To customize metadata extraction, check out the documentation for your serializer.
Autotracking is how Ember's reactivity model works - how it decides what to rerender, and when. This guide covers tracking in more depth, including how it can be used in various types of classes, and how it interacts with arrays and POJOs.
 
When Ember first renders a component, it renders the initial state of that component - the state of the instance, and state of the arguments that are passed to it:
 
app/components/hello.hbs :
{{this.greeting}}, {{@name}}!
app/components/hello.js :
import Component from '@glimmer/component';

export default class HelloComponent extends Component {
  language = 'en';

  get greeting() {
    switch (this.language) {
      case 'en':
        return 'Hello';
      case 'de':
        return 'Hallo';
      case 'es':
        return 'Hola';
    }
  }
}
app/templates/application.hbs
<Hello @name="Free Time Learning">
When Ember renders this template, we get:
Hello, Free Time Learning!
Native classes were first added to JavaScript in ES2015 (also known as ES6). They are defined using the class keyword, and look like this :
class Person {
  helloWorld() {
    console.log('Hello, world!');
  }
}
Ember applications utilize the dependency injection ("DI") design pattern to declare and instantiate classes of objects and dependencies between them.
 
Generally, Services are Ember's primary method for sharing state via dependency injection. In most cases, you shouldn't need to learn about how to work with Ember's DI system directly, or how to manually register and setup dependencies. However, there are times when it may be necessary. 
Initializers provide an opportunity to configure your application as it boots.
 
There are two types of initializers :
* Application initializers
* Application instance initializers

Application initializers : Application initializers can be created with Ember CLI's initializer generator:
ember generate initializer shopping-cart
Let's customize the shopping-cart initializer to inject a cart property into all the routes in your application:
 
app/initializers/shopping-cart.js :
export function initialize(application) {
  application.inject('route', 'cart', 'service:shopping-cart');
};

export default {
  initialize
};
 
Application Instance Initializers : Application instance initializers can be created with Ember CLI's instance-initializer generator :
ember generate instance-initializer logger
Let's add some simple logging to indicate that the instance has booted:
 
app/instance-initializers/logger.js :
export function initialize(applicationInstance) {
  let logger = applicationInstance.lookup('logger:main');
  logger.log('Hello from the instance initializer!');
}

export default {
  initialize
};
The most common case for using the run loop is integrating with a non-Ember API that includes some sort of asynchronous callback.

For example :
 
* DOM update and event callbacks
* setTimeout and setInterval callbacks
* postMessage and messageChannel event handlers
* fetch or ajax callbacks
* WebSocket callbacks
Very often, batching similar work has benefits. Web browsers do something quite similar by batching changes to the DOM.
 
Consider the following HTML snippet :
<div id="foo"></div>
<div id="bar"></div>
<div id="baz"></div>
 
and executing the following code :
foo.style.height = '500px' // write
foo.offsetHeight // read (recalculate style, layout, expensive!)

bar.style.height = '400px' // write
bar.offsetHeight // read (recalculate style, layout, expensive!)

baz.style.height = '200px' // write
baz.offsetHeight // read (recalculate style, layout, expensive!)
Ember Engines allow multiple logical applications to be composed together into a single application from the user's perspective, that provide functionality to their host applications. Engines are isolated, composable applications, they have almost all the same features as normal Ember applications, except an Engine requires a host application to boot it and provide a Router instance.