From 933433ceea375e97914bc577a34722d56ed3b9fb Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Tue, 15 Dec 2015 14:10:10 -0800 Subject: [PATCH] fix(template syntax): minor fixes closes #535 --- .../docs/ts/latest/guide/template-syntax.jade | 160 +++++++++--------- 1 file changed, 78 insertions(+), 82 deletions(-) diff --git a/public/docs/ts/latest/guide/template-syntax.jade b/public/docs/ts/latest/guide/template-syntax.jade index a7043de079..dafbe16206 100644 --- a/public/docs/ts/latest/guide/template-syntax.jade +++ b/public/docs/ts/latest/guide/template-syntax.jade @@ -35,7 +35,7 @@ include ../../../../_includes/_util-fns >[Input and Output Properties](#inputs-outputs) >[Template Expression Operators](#expression-operators) - + [Live Example](/resources/live-examples/template-syntax/ts/plnkr.html). .l-main-section @@ -118,7 +118,7 @@ include ../../../../_includes/_util-fns The component itself is usually the expression *context* in which case the template expression usually references that component. The expression context may include an object other than the component. - + A [local template variable](#local-vars) is one such supplemental context object; we’ll discuss that option below. @@ -192,7 +192,7 @@ table But it’s also significantly different than the HTML we’re used to. We really need a new mental model. - In the normal course of HTML development, we create a visual structure with HTML elements and + In the normal course of HTML development, we create a visual structure with HTML elements and we modify those elements by setting element attributes with string constants. +makeExample('template-syntax/ts/app/app.component.html', 'img+button')(format=".") :marked @@ -330,10 +330,6 @@ table +makeExample('template-syntax/ts/app/app.component.html', 'style-binding-syntax-1')(format=".") -.l-sub-section - :marked - According to this rule, we should write `[inner-h-t-m-l]` to access the element’s `innerHTML` property. - Fortunately, the Angular template parser recognizes `inner-html` as an acceptable alias for `innerHTML`. :marked Let’s descend from the architectural clouds and look at each of these binding types in concrete detail. @@ -407,7 +403,7 @@ table ### Property Binding or Interpolation? We often have a choice between Interpolation and Property Binding. The following binding pairs do the same thing - + +makeExample('template-syntax/ts/app/app.component.html', 'property-binding-vs-interpolation')(format=".") :marked Interpolation is actually a convenient alternative for Property Binding in many cases. @@ -452,7 +448,7 @@ code-example(format="", language="html"). Can't bind to 'colspan' since it isn't a known native property :marked As the message says, the `` element does not have a `colspan` property. - It has the "colspan" *attribute* but + It has the "colspan" *attribute* but interpolation and property binding can only set properties, not attributes. We need an Attribute Binding to create and bind to such attributes. @@ -466,7 +462,7 @@ code-example(format="", language="html"). :marked Here's how the table renders: - +
One-Two
One-Two
FiveSix
@@ -475,11 +471,11 @@ code-example(format="", language="html"). +makeExample('template-syntax/ts/app/app.component.html', 'attrib-binding-aria')(format=".") :marked ### Class Binding - + We can add and remove CSS class names from an element’s `class` attribute with the **Class Binding**. - Class Binding syntax resembles Property Binding. - Instead of an element property between brackets, we start with the keyword `class` followed + Class Binding syntax resembles Property Binding. + Instead of an element property between brackets, we start with the keyword `class` followed by the name of a CSS class: `[class.class-name]`. In the following examples we see how to add and remove the application's "special" class @@ -490,7 +486,7 @@ code-example(format="", language="html"). +makeExample('template-syntax/ts/app/app.component.html', 'class-binding-2')(format=".") :marked Finally, we bind to a specific class name. - Angular adds the class when the template expression evaluates to something truthy and + Angular adds the class when the template expression evaluates to something truthy and removes the class name when the expression is falsey. +makeExample('template-syntax/ts/app/app.component.html', 'class-binding-3')(format=".") @@ -504,8 +500,8 @@ code-example(format="", language="html"). We can set inline styles with a **Style Binding**. - Style Binding syntax resembles Property Binding. - Instead of an element property between brackets, we start with the key word `style` + Style Binding syntax resembles Property Binding. + Instead of an element property between brackets, we start with the key word `style` followed by the name of a CSS style property: `[style.style-property]`. +makeExample('template-syntax/ts/app/app.component.html', 'style-binding-1')(format=".") @@ -547,7 +543,7 @@ code-example(format="", language="html"). of a known directive as it does in the following example: +makeExample('template-syntax/ts/app/app.component.html', 'event-binding-3')(format=".") :marked - If the name fails to match an element event or an output property of a known directive, + If the name fails to match an element event or an output property of a known directive, Angular reports an “unknown directive” error. ### $event and event handling expressions @@ -568,16 +564,16 @@ code-example(format="", language="html"). Consider this example: +makeExample('template-syntax/ts/app/app.component.html', 'without-NgModel')(format=".") :marked - We’re binding the input box `value` to a `firstName` property and we’re listening for changes by binding to the input box’s `input` event. - When the user makes changes, the `input` event is raised, and the binding executes the expression within a context that includes the DOM event object, `$event`. - + We’re binding the input box `value` to a `firstName` property and we’re listening for changes by binding to the input box’s `input` event. + When the user makes changes, the `input` event is raised, and the binding executes the expression within a context that includes the DOM event object, `$event`. + We must follow the `$event.target.value` path to get the changed text so we can update the `firstName` - If the event belongs to a directive (remember: components are directives), `$event` has whatever shape the directive chose to produce. - Consider a `HeroDetailComponent` that produces `deleted` events with an `EventEmitter`. + If the event belongs to a directive (remember: components are directives), `$event` has whatever shape the directive chose to produce. + Consider a `HeroDetailComponent` that produces `deleted` events with an `EventEmitter`. +makeExample('template-syntax/ts/app/hero-detail.component.ts', 'deleted', 'HeroDetailComponent.ts (excerpt)')(format=".") :marked - When something invokes the `onDeleted()` method, we "emit" a `Hero` object. + When something invokes the `onDeleted()` method, we "emit" a `Hero` object. Now imagine a parent component that listens for that event with an Event Binding. +makeExample('template-syntax/ts/app/app.component.html', 'event-binding-to-component')(format=".") @@ -588,7 +584,7 @@ code-example(format="", language="html"). Evaluation of an Event Binding template expression may have side-effects as this one clearly does. They are not just OK (unlike in property bindings); they are expected. - + The expression could update the model thereby triggering other changes that percolate through the system, changes that are ultimately displayed in this view and other views. The event processing may result in queries and saves to a remote server. It's all good. @@ -609,7 +605,7 @@ code-example(format="", language="html"). continues or stops with the current element. Event propagation stops if the binding expression returns a falsey value (as does a method with no return value). - Clicking the button in this next example triggers a save; + Clicking the button in this next example triggers a save; the click doesn't make it to the outer `
` so it's save is not called: +makeExample('template-syntax/ts/app/app.component.html', 'event-binding-no-propagation')(format=".") :marked @@ -645,7 +641,7 @@ code-example(format="", language="html"). +makeExample('template-syntax/ts/app/app.component.html', 'NgModel-3')(format=".") :marked That’s an improvement. It should be better. - + We shouldn't have to mention the data property twice. Angular should be able to read the component’s data property and set it with a single declaration — which it can with the `[{ }]` syntax: +makeExample('template-syntax/ts/app/app.component.html', 'NgModel-1')(format=".") @@ -659,11 +655,11 @@ code-example(format="", language="html"). We can write our own two-way binding directive that follows this pattern if we're ever in the mood to do so. :marked - Is `[{ngModel}]` all we need? Is there ever a reason to fall back to its expanded form? - - Well `NgModel` can only set the target property. + Is `[(ngModel)]` all we need? Is there ever a reason to fall back to its expanded form? + + Well `NgModel` can only set the target property. What if we need to do something more or something different when the user changes the value? - + Let's try something silly like forcing the input value to uppercase. +makeExample('template-syntax/ts/app/app.component.html', 'NgModel-4')(format=".") :marked @@ -677,7 +673,7 @@ figure.image-display ## Built-in Directives - Earlier versions of Angular included over seventy built-in directives. + Earlier versions of Angular included over seventy built-in directives. The community contributed many more and individuals have created countless private directives for internal applications. We don’t need many of those directives in Angular 2. @@ -727,7 +723,7 @@ figure.image-display The `NgStyle` directive may be the better choice when we want to set *many* inline styles at the same time. - We apply `NgStyle` by binding it to a key:value control object. + We apply `NgStyle` by binding it to a key:value control object. Each key of the object is a style name and its value is whatever is appropriate for that style. Consider a component method such as `setStyles` that returns an object defining three styles: @@ -761,25 +757,25 @@ figure.image-display :marked Hiding a sub-tree is quite different from excluding a sub-tree with `NgIf`. - When we hide the element sub-tree, it remains in the DOM. - Components in the sub-tree are preserved along with their state. - Angular may continue to check for changes even to invisible properties. + When we hide the element sub-tree, it remains in the DOM. + Components in the sub-tree are preserved along with their state. + Angular may continue to check for changes even to invisible properties. The sub-tree may tie up substantial memory and computing resources. - When `NgIf` is `false`, Angular physically removes the element sub-tree from the DOM. - It destroys components in the sub-tree along with their state which may free up substantial resources + When `NgIf` is `false`, Angular physically removes the element sub-tree from the DOM. + It destroys components in the sub-tree along with their state which may free up substantial resources resulting in better performance for the user. - The show/hide technique is probably fine for small element trees. + The show/hide technique is probably fine for small element trees. We should be wary when hiding large trees; `NgIf` may be the safer choice. Always measure before leaping to conclusions. - + .l-main-section :marked ### NgSwitch We bind to `NgSwitch` when we want to display *one* element tree (an element and its children) from a *set* of possible elment trees based on some condition. - Angular only puts the *selected* element tree into the DOM. + Angular only puts the *selected* element tree into the DOM. Here’s an example: +makeExample('template-syntax/ts/app/app.component.html', 'NgSwitch')(format=".") @@ -802,10 +798,10 @@ figure.image-display :marked ### NgFor `NgFor` is a “repeater” directive. It will be familiar if we’ve written repeaters for other view engines. - + Our goal is to present a list of items. We define a block of HTML that defines how a single item should be displayed. We tell Angular to use that block as a template for rendering each item in the list. - + Here is an example of `NgFor` applied to a simple `
`. +makeExample('template-syntax/ts/app/app.component.html', 'NgFor-1')(format=".") :marked @@ -814,7 +810,7 @@ figure.image-display .alert.is-critical :marked - The leading asterisk (\*) in front of `ngFor` is a critical part of this syntax. + The leading asterisk (\*) in front of `ngFor` is a critical part of this syntax. See the section below on [\* and <template>](#star-template). :marked The text assigned to `*ngFor` is the instruction that guides the repeater process. @@ -822,26 +818,26 @@ figure.image-display .l-sub-section :marked #### NgFor Micro-syntax - The string assigned to `*ngFor` is not a [template expression](#template-expressions). + The string assigned to `*ngFor` is not a [template expression](#template-expressions). It’s a little language of its own called a “micro-syntax” that Angular interprets. In this example it means: - + >*Take each hero in the `heroes` array, store it in the local `hero` variable, and make it available to the templated HTML for each iteration*. - + Angular translates this instruction into a new set of elements and bindings. We’ll talk about this in the next section about templates. :marked - In our two examples, the `ngFor` directive iterates over the `heroes` array returned by the parent component’s `heroes` property + In our two examples, the `ngFor` directive iterates over the `heroes` array returned by the parent component’s `heroes` property and stamps out instances of the element to which it is applied. Angular creates a fresh instance of the template for each hero in the array. - + The (#) character before "hero" identifies a [local template variable](#local-vars) called `hero`. - + We reference this variable within the template to access a hero’s properties as we’re doing in the interpolation - or we can pass it in a binding to a component element as we're doing with `hero-detail`. - + or we can pass it in a binding to a component element as we're doing with `hero-detail`. + #### NgFor with index - The `ngFor` directive supports an optional index that increases from 0 to the length of the array for each iteration. + The `ngFor` directive supports an optional index that increases from 0 to the length of the array for each iteration. We can capture that in another local template variable (`i`) and use it in our template too. This next example stamps out rows that display like "1 - Hercules Son of Zeus": @@ -868,9 +864,9 @@ figure.image-display the *template-to-repeat* and the *template-to-include* respectively. The (\*) prefix syntax is a convenient way for developers to skip the `