Create a gist now

Instantly share code, notes, and snippets.

@wycats /rendering.md Secret
Last active Dec 12, 2015

What would you like to do?

DISCLAIMER

The contents of this gist are no longer up to date and do not reflect changes in thinking and implementation since it was created.

Inserting a component into the page

A component is a triple of:

  1. A template
  2. A controller (for a model)
  3. A view

A component name represents all aspects of this triple, looked up via a container:

  1. container.lookup('template:<name>')
  2. container.lookup('controller:<name>')
  3. container.lookup('view:<name>')

By default, the template for a component is a template which does not modify the buffer.

By default, the view for a component is the DefaultView, which is a simple virtual (Metamorph) view.

By default, the controller for a component depends on the model:

  • If the model is an object, the controller is a generated ObjectController
  • If the model implements Ember.Array, the controller is a generated ArrayController
  • Otherwise, the controller is a generated Controller

Container Lookup

A component is always built in the context of a container. The operations that generate a component may use different containers.

Render

{{render "<name>" <model>?}}

  1. if <model> is specified, let model be the result of evaluating <model> in the current template context.
  2. otherwise, let model be undefined.
  3. let container be the container for the current controller.
  4. let view be the result of evaluating the algorithm Build a Component with the parameters container, <name>, and model.
  5. append view to the current view.

Control

{{control "<name>" <model>?}}

  1. if <model> is specified, let model be the result of evaluating <model> in the current template context.
  2. otherwise, let model be undefined.
  3. let parentContainer be the container for the current controller.
  4. let key be the controlID for the {{control}} helper.
  5. let container be the result of evaluating the algorithm Retrieve a Child Container with the arguments parentContainer,
  6. let view be the result of evaluating the algorithm Build a Component with the parameters container, <name>, and model.
  7. append view to the current view.

Render into Outlet

this.render("<name>")

This algorithm inherits a container from its calling context.

This algorithm assumes an outletView (a subclass of ContainerView, determined from other parameters and ambient state).

This algorithm assumes that previous code has already generated and populated the controller for <name>, so a lookup for controller:<name> on container will always succeed.

  1. let view be the result of evaluating the algorithm Build a Component with the parameters container, <name> and undefined (for model).
  2. set the 'currentView' property of outletView to view.

Each

{{#each <model> render="<name>"?}} or {{each <model> render="<name>"?}}

  1. if model does not implement Ember.Array, throw an exception.
  2. if <name> is not specified and there is no inline template supplied by the template engine, throw an exception.
  3. if an inline template is supplied by the templating engine, let template be that template
  4. otherwise, let template be undefined.
  5. let model be the result of evaluating <model> in the current template context.
  6. let parentView be the current view.
  7. let controller be the current controller.
  8. let parentContainer be the container for the current controller.
  9. let view be a new virtual (Metamorph) instance of Ember.CollectionView.
  10. let the current view be view.
  11. let key be the controlID for the {{each}} helper
  12. let containerList be the result of evaluating the algorithm Retrieve a Container List with the parameters controller and key.
  13. Evaluate the algorithm Render a List with the parameters parentContainer, <name>, template, model, and containerList.
  14. append view to parentView.

Render a List

This algorithm takes parentContainer, name, template, model, and containerList as parameters.

  1. if model does not implement Ember.Array, throw an exception.
  2. for each item in model with index i:
    1. let container be the item at position i in containerList.
    2. if container is undefined
      1. let container be a new child container for parentContainer.
      2. insert container in containerList at position i.
    3. let view be the result of evaluating the algorithm Build a Component with the parameters container, name, item, and template.
    4. append view to the current view.
  3. when an item is removed from the model array, destroy the container at the same position in containerList and destroy the view created by 2.3.
  4. when an item is added to the model array, follow 2 for the new item; the containers in the containerList should reflect their associated items in the model.

Retrieve a Child Container

This algorithm takes parentContainer, controller, and key as parameters.

  1. let containers be an internal map of child containers for controller.
  2. let container be the container for key in containers.
  3. if container is not undefined, return container.
  4. let container be a new child container for parentContainer.
  5. insert container into containers for key.
  6. when the 'model' property of controller changes, destroy container and delete key from the internal map of child containers.
  7. return container.

Retrieve a Container List

This algorithm takes controller, and key as parameters.

  1. let containers be an internal map of child containers for controller.
  2. let containerList be the container list for key in containers.
  3. if containerList is not undefined, return containerList.
  4. let containerList be a new container list.
  5. insert containerList into containers for key.
  6. when the 'model' property of controller changes, destroy all containers in containerList and delete key from the internal map of child containers
  7. return containerList.

Build a Component

This algorithm takes container, name, and model as parameters.

This algorithm takes template as an optional parameter.

If name is undefined:

  1. if template is undefined, throw an exception.
  2. if model is undefined, let childController be a new, anonymous subclass of Ember.Controller
  3. let view be an instance of a new, anonymous subclass of Ember._Metamorph.

If name is not undefined:

  1. let childController be the result of looking up 'controller:<name>' on container.
  2. if childController is undefined, then childController is the result of evaluating Generate a Controller with the parameters container and model and name.
  3. set the 'model' property of childController to model.
  4. if template is undefined, late template be the result of looking up 'template:<name>' on container.
  5. if template is still undefined, let template be a new function that returns the empty string.
  6. let view be the result of looking up 'view:<name>' on container.
  7. if view is undefined, let view be an instance of a new, anonymous subclass of Ember._Metamorph.

In either case, continue as follows:

  1. set the 'controller' property of view to childController.
  2. set the 'target' property of childController to controller.
  3. set the 'template' property of view to template.
  4. return view.

Generate a Controller

This algorithm takes container, model and name as parameters.

  1. If model implements Ember.Array, let controllerClass be a new, anonymous subclass of Ember.ArrayController
  2. Otherwise, if model is not null, undefined, false, the empty string or 0, let controllerClass be a new, anonymous subclass of Ember.ObjectController
  3. Otherwise, let controllerClass be a new, anonymous subclass of Ember.Controller
  4. register controllerClass as the factory for controller:<name> on container.
  5. return the result of looking up controller:<name> on container.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment