Skip to content

Commit

Permalink
refactor(compiler): remove Viewport directives, use Decorator ins…
Browse files Browse the repository at this point in the history
…tead

BREAKING_CHANGE:
- The special type of `Viewport` directives is removed
  in favor of a more general `Decorator` directive
- `ViewContainerRef` now no more has a default `ProtoViewRef`
  but requires an explicit one when creating views.

Closes #1536
  • Loading branch information
tbosch committed Apr 29, 2015
1 parent fb67e37 commit 3aac2fe
Show file tree
Hide file tree
Showing 35 changed files with 219 additions and 305 deletions.
12 changes: 5 additions & 7 deletions modules/angular2/docs/core/01_templates.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ projected to DOM as well as which DOM events should invoke which methods on the
syntax which is core to Angular and allows for data-binding, event-binding, template-instantiation. syntax which is core to Angular and allows for data-binding, event-binding, template-instantiation.


The design of the template syntax has these properties: The design of the template syntax has these properties:



* All data-binding expressions are easily identifiable. (i.e. there is never an ambiguity whether the value should be * All data-binding expressions are easily identifiable. (i.e. there is never an ambiguity whether the value should be
interpreted as string literal or as an expression.) interpreted as string literal or as an expression.)
Expand Down Expand Up @@ -372,8 +372,8 @@ Where:
inserted. The template can be defined implicitly with `template` attribute, which turns the current element into inserted. The template can be defined implicitly with `template` attribute, which turns the current element into
a template, or explicitly with `<template>` element. Explicit declaration is longer, but it allows for having a template, or explicitly with `<template>` element. Explicit declaration is longer, but it allows for having
templates which have more than one root DOM node. templates which have more than one root DOM node.
* `viewport` is required for templates. The Viewport directive is responsible for deciding when * `viewport` is required for templates. The directive is responsible for deciding when
and in which order should child views be inserted into this location. An Viewport directive usually has one or and in which order should child views be inserted into this location. Such a directive usually has one or
more bindings and can be represented as either `viewport-directive-bindings` or more bindings and can be represented as either `viewport-directive-bindings` or
`viewport-directive-microsyntax` on `template` element or attribute. See template microsyntax for more details. `viewport-directive-microsyntax` on `template` element or attribute. See template microsyntax for more details.


Expand All @@ -387,7 +387,7 @@ Hello {{user}}!
</div> </div>
``` ```


In the above example the `if` Viewport determines whether the child view (an instance of the child template) should be In the above example the `if` directive determines whether the child view (an instance of the child template) should be
inserted into the root view. The `if` makes this decision based on if the `isAdministrator` binding is true. inserted into the root view. The `if` makes this decision based on if the `isAdministrator` binding is true.


The above example is in the short form, for better clarity let's rewrite it in the canonical form, which is functionally The above example is in the short form, for better clarity let's rewrite it in the canonical form, which is functionally
Expand All @@ -402,8 +402,6 @@ Hello {{user}}!
</template> </template>
``` ```


NOTE: Only Viewport directives can be placed on the template element. (Decorators and Components are not allowed.)



### Template Microsyntax ### Template Microsyntax


Expand Down Expand Up @@ -514,7 +512,7 @@ Where:
* `some-element` Any element which can generate DOM events (or has an angular directive which generates the event). * `some-element` Any element which can generate DOM events (or has an angular directive which generates the event).
* `some-event` (escaped with `()` or `on-`) is the name of the event `some-event`. In this case the * `some-event` (escaped with `()` or `on-`) is the name of the event `some-event`. In this case the
dash-case is converted into camel-case `someEvent`. dash-case is converted into camel-case `someEvent`.
* `statement` is a valid statement (as defined in section below). * `statement` is a valid statement (as defined in section below).
If the execution of the statement returns `false`, then `preventDefault`is applied on the DOM event. If the execution of the statement returns `false`, then `preventDefault`is applied on the DOM event.


By default, angular only listens to the element on the event, and ignores events which bubble. To listen to bubbled By default, angular only listens to the element on the event, and ignores events which bubble. To listen to bubbled
Expand Down
29 changes: 14 additions & 15 deletions modules/angular2/docs/core/02_directives.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ There are three different kinds of directives (described in more detail in later


1. *Decorators*: can be placed on any DOM element and can be combined with other directives. 1. *Decorators*: can be placed on any DOM element and can be combined with other directives.
2. *Components*: Components have an encapsulated view and can configure injectors. 2. *Components*: Components have an encapsulated view and can configure injectors.
3. *Viewport*: is responsible for adding or removing child views in a parent view. (i.e. for, if)






Expand Down Expand Up @@ -163,39 +162,39 @@ Example of usage:






## Viewport ## Directives that use a ViewContainer


Viewport is a directive which can control instantiation of child views which are then inserted into the DOM. (Examples are `if` and `for`.) Directives that use a ViewContainer can control instantiation of child views which are then inserted into the DOM. (Examples are `if` and `for`.)


* Viewports can only be placed on `<template>` elements (or the short hand version which uses `<element template>` attribute.) * Every `template` element creates a `ProtoView` which can be used to create Views via the ViewContainer.
* Only one viewport can be present per DOM template element. * The child views show up as siblings of the directive in the DOM.
* The viewport is created over the `template` element. This is known as the `ViewContainerRef`.
* Viewport can insert child views into the `ViewContainerRef`. The child views show up as siblings of the `Viewport` in the DOM.


>> TODO(misko): Relationship with Injection >> TODO(misko): Relationship with Injection
>> TODO(misko): Instantiator can not be injected into child Views >> TODO(misko): Instantiator can not be injected into child Views


``` ```
@Viewport({ @Directive({

This comment has been minimized.

Copy link
@0x-r4bbit

0x-r4bbit Apr 30, 2015

Contributor

So this really becomes Directive and not Decorator ?

This comment has been minimized.

Copy link
@tbosch

tbosch Apr 30, 2015

Author Contributor

Yes, in one of my next PRs...

selector: '[if]', selector: '[if]',
properties: { properties: {
'condition': 'if' 'condition': 'if'
} }
}) })
export class If { export class If {
viewContainer: ViewContainerRef; viewContainer: ViewContainerRef;
protoViewRef: ProtoViewRef;
view: View; view: View;
constructor(viewContainer: ViewContainerRef) { constructor(viewContainer: ViewContainerRef, protoViewRef: ProtoViewRef) {
this.viewContainer = viewContainer; this.viewContainer = viewContainer;
this.protoViewRef = protoViewRef;
this.view = null; this.view = null;
} }
set condition(value) { set condition(value) {
if (value) { if (value) {
if (this.view === null) { if (this.view === null) {
this.view = this.viewContainer.create(); this.view = this.viewContainer.create(protoViewRef);
} }
} else { } else {
if (this.view !== null) { if (this.view !== null) {
Expand Down Expand Up @@ -342,7 +341,7 @@ Shadow DOM provides an encapsulation for components, so as a general rule it doe
}) })
class Kid { class Kid {
constructor( constructor(
@Parent() dad:Dad, @Parent() dad:Dad,
@Optional() grandpa:Grandpa @Optional() grandpa:Grandpa
) { ) {
this.name = 'Billy'; this.name = 'Billy';
Expand All @@ -365,7 +364,7 @@ class Dad {
this.dad = dad.name; this.dad = dad.name;
console.log(dad) console.log(dad)
} }
} }
@Component({ @Component({
selector: '[grandpa]', selector: '[grandpa]',
Expand All @@ -379,17 +378,17 @@ class Grandpa {
constructor() { constructor() {
this.name = 'Joe'; this.name = 'Joe';
} }
} }
``` ```


Assume the following DOM structure for `grandpa.html`: The Dad has access to the Grandpa. Assume the following DOM structure for `grandpa.html`: The Dad has access to the Grandpa.
``` ```
Name: {{name}}: <br> Children: <div dad></div> Name: {{name}}: <br> Children: <div dad></div>
``` ```


Assume the following DOM structure for `dad.html`: Here the rendered Kid will also have access to Grandpa. Assume the following DOM structure for `dad.html`: Here the rendered Kid will also have access to Grandpa.
``` ```
Name: {{name}}: <br> Dad: {{dad}} <br> Children: <div kid></div> Name: {{name}}: <br> Dad: {{dad}} <br> Children: <div kid></div>
``` ```


## Further Reading ## Further Reading
Expand Down
22 changes: 11 additions & 11 deletions modules/angular2/docs/core/10_view.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@


This document explains the concept of a View. This document explains the concept of a View.
A View is a core primitive used by angular to render the DOM tree. A View is a core primitive used by angular to render the DOM tree.
A ViewPort is location in a View which can accept child Views. A ViewContainer is location in a View which can accept child Views.
Every ViewPort has an associated ViewContainerRef than can contain any number of child Views. Every ViewContainer has an associated ViewContainerRef than can contain any number of child Views.
Views form a tree structure which mimics the DOM tree. Views form a tree structure which mimics the DOM tree.


* View is a core rendering construct. A running application is just a collection of Views which are * View is a core rendering construct. A running application is just a collection of Views which are
Expand All @@ -15,7 +15,7 @@ Views form a tree structure which mimics the DOM tree.
* Views represent a running instance of a DOM View. This implies that while elements in a View * Views represent a running instance of a DOM View. This implies that while elements in a View
can change properties, they can not change structurally. (Structural changes such as, adding or can change properties, they can not change structurally. (Structural changes such as, adding or
removing elements requires adding or removing child Views into ViewContainers). removing elements requires adding or removing child Views into ViewContainers).
* View can have zero or more ViewPorts. A ViewPort is a marker in the DOM which allows * View can have zero or more ViewContainers. A ViewContainer is a marker in the DOM which allows
the insertion of child Views. the insertion of child Views.
* Views are created from a ProtoView. A ProtoView is a compiled DOM View which is efficient at * Views are created from a ProtoView. A ProtoView is a compiled DOM View which is efficient at
creating Views. creating Views.
Expand Down Expand Up @@ -88,7 +88,7 @@ Note:
## Composed View ## Composed View


An important part of an application is to be able to change the DOM structure to render data for the An important part of an application is to be able to change the DOM structure to render data for the
user. In Angular this is done by inserting child views into the ViewPort. user. In Angular this is done by inserting child views into the ViewContainer.


Let's start with a View such as: Let's start with a View such as:


Expand All @@ -108,7 +108,7 @@ and


``` ```
<ul> | protoViewA(someContext) <ul> | protoViewA(someContext)
<template></template> | protoViewA(someContext): new ProtoViewPort(protoViewB) <template></template> | protoViewA(someContext): protoViewB
</ul> | protoViewA(someContext) </ul> | protoViewA(someContext)
``` ```


Expand All @@ -119,7 +119,7 @@ The next step is to compose these two ProtoViews into an actual view which is re


``` ```
<ul> | viewA(someContext) <ul> | viewA(someContext)
<template></template> | viewA(someContext): new Foreach(new ViewPort(protoViewB)) <template></template> | viewA(someContext): new Foreach(new ViewContainer(protoViewB))
</ul> | viewA(someContext) </ul> | viewA(someContext)
``` ```


Expand All @@ -128,11 +128,11 @@ has a reference to `protoViewA`).




*Step3:* As the `Foreach` directive unrolls it asks the `ViewContainerRef` to instantiate `protoViewB` and insert *Step3:* As the `Foreach` directive unrolls it asks the `ViewContainerRef` to instantiate `protoViewB` and insert
it after the `ViewPort` anchor. This is repeated for each `person` in `people`. Notice that it after the `ViewContainer` anchor. This is repeated for each `person` in `people`. Notice that


``` ```
<ul> | viewA(someContext) <ul> | viewA(someContext)
<template></template> | viewA(someContext): new Foreach(new ViewPort(protoViewB)) <template></template> | viewA(someContext): new Foreach(new ViewContainer(protoViewB))
<li>{{person}}</li> | viewB0(locals0(someContext)) <li>{{person}}</li> | viewB0(locals0(someContext))
<li>{{person}}</li> | viewB1(locals0(someContext)) <li>{{person}}</li> | viewB1(locals0(someContext))
</ul> | viewA(someContext) </ul> | viewA(someContext)
Expand All @@ -145,13 +145,13 @@ delegate any unknown references to the parent context.


``` ```
<ul> | viewA <ul> | viewA
<template></template> | viewA: new Foreach(new ViewPort(protoViewB)) <template></template> | viewA: new Foreach(new ViewContainer(protoViewB))
<li>Alice</li> | viewB0 <li>Alice</li> | viewB0
<li>Bob</li> | viewB1 <li>Bob</li> | viewB1
</ul> | viewA </ul> | viewA
``` ```


Each View can have zero or more ViewPorts. By inserting and removing child Views to and from the Each View can have zero or more ViewContainers. By inserting and removing child Views to and from the
ViewContainers, the application can mutate the DOM structure to any desirable state. A View may contain ViewContainers, the application can mutate the DOM structure to any desirable state. A View may contain
individual nodes or a complex DOM structure. The insertion points for the child Views, known as individual nodes or a complex DOM structure. The insertion points for the child Views, known as
ViewContainers, contain a DOM element which acts as an anchor. The anchor is either a `template` or ViewContainers, contain a DOM element which acts as an anchor. The anchor is either a `template` or
Expand All @@ -161,7 +161,7 @@ inserted.
## Component Views ## Component Views


A View can also contain Components. Components contain Shadow DOM for encapsulating their internal A View can also contain Components. Components contain Shadow DOM for encapsulating their internal
rendering state. Unlike ViewPorts which can contain zero or more Views, the Component always contains rendering state. Unlike ViewContainers which can contain zero or more Views, the Component always contains
exactly one Shadow View. exactly one Shadow View.


``` ```
Expand Down
Loading

0 comments on commit 3aac2fe

Please sign in to comment.