279 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			279 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
block includes
 | 
						|
  include ../_util-fns
 | 
						|
  - var _iterableUrl = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols';
 | 
						|
  - var _boolean = 'truthy/falsey';
 | 
						|
 | 
						|
:marked
 | 
						|
  You can display data by binding controls in an HTML template to properties of an Angular component.
 | 
						|
 | 
						|
  In this page, you'll create a component with a list of heroes.
 | 
						|
  You'll display the list of hero names and
 | 
						|
  conditionally show a message below the list.
 | 
						|
 | 
						|
  The final UI looks like this:
 | 
						|
 | 
						|
figure.image-display
 | 
						|
  img(src="/resources/images/devguide/displaying-data/final.png" alt="Final UI")
 | 
						|
 | 
						|
:marked
 | 
						|
  # Contents
 | 
						|
 | 
						|
  * [Showing component properties with interpolation](#interpolation).
 | 
						|
  * [Showing !{_an} !{_array} property with NgFor](#ngFor).
 | 
						|
  * [Conditional display with NgIf](#ngIf).
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    The <live-example></live-example> demonstrates all of the syntax and code
 | 
						|
    snippets described in this page.
 | 
						|
 | 
						|
.l-main-section#interpolation
 | 
						|
:marked
 | 
						|
  ## Showing component properties with interpolation
 | 
						|
  The easiest way to display a component property
 | 
						|
  is to bind the property name through interpolation.
 | 
						|
  With interpolation, you put the property name in the view template, enclosed in double curly braces: `{{myHero}}`.
 | 
						|
 | 
						|
  To build an illustrative example, start by creating a new project folder called <ngio-ex path="displaying-data"></ngio-ex>
 | 
						|
  and following the steps in [QuickStart](../quickstart.html).
 | 
						|
 | 
						|
block quickstart-repo
 | 
						|
  include ../_quickstart_repo
 | 
						|
 | 
						|
:marked
 | 
						|
  Then modify the <ngio-ex path="app.component.ts"></ngio-ex> file by
 | 
						|
  changing the template and the body of the component.
 | 
						|
 | 
						|
  When you're done, it should look like this:
 | 
						|
 | 
						|
+makeExample('app/app.component.1.ts')
 | 
						|
 | 
						|
:marked
 | 
						|
  You added two properties to the formerly empty component: `title` and `myHero`.
 | 
						|
 | 
						|
  The revised template displays the two component properties using double curly brace
 | 
						|
  interpolation:
 | 
						|
 | 
						|
+makeExcerpt('app/app.component.1.ts', 'template', '')
 | 
						|
 | 
						|
+ifDocsFor('ts')
 | 
						|
  .l-sub-section
 | 
						|
    :marked
 | 
						|
      The template is a multi-line string within ECMAScript 2015 backticks (<code>\`</code>).
 | 
						|
      The backtick (<code>\`</code>)—which is *not* the same character as a single
 | 
						|
      quote (`'`)—allows you to compose a string over several lines, which makes the
 | 
						|
      HTML more readable.
 | 
						|
 | 
						|
:marked
 | 
						|
  Angular automatically pulls the value of the `title` and `myHero` properties from the component and
 | 
						|
  inserts those values into the browser. Angular updates the display
 | 
						|
  when these properties change.
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    More precisely, the redisplay occurs after some kind of asynchronous event related to
 | 
						|
    the view, such as a keystroke, a timer completion, or a response to an HTTP request.
 | 
						|
 | 
						|
:marked
 | 
						|
  Notice that you don't call **new** to create an instance of the `AppComponent` class.
 | 
						|
  Angular is creating an instance for you. How?
 | 
						|
 | 
						|
  The CSS `selector` in the `@Component` !{_decorator} specifies an element named `my-app`.
 | 
						|
  Remember back in [QuickStart](../quickstart.html) that you added the `<my-app>`
 | 
						|
  element to the body of your `index.html` file:
 | 
						|
 | 
						|
+makeExcerpt('index.html', 'body')
 | 
						|
 | 
						|
:marked
 | 
						|
  When you bootstrap with the `AppComponent` class (in <ngio-ex path="main.ts"></ngio-ex>), Angular looks for a `<my-app>`
 | 
						|
  in the `index.html`, finds it, instantiates an instance of `AppComponent`, and renders it
 | 
						|
  inside the `<my-app>` tag.
 | 
						|
 | 
						|
  Now run the app. It should display the title and hero name:
 | 
						|
figure.image-display
 | 
						|
  img(src="/resources/images/devguide/displaying-data/title-and-hero.png" alt="Title and Hero")
 | 
						|
 | 
						|
+ifDocsFor('ts')
 | 
						|
  :marked
 | 
						|
    The next few sections review some of the coding choices in the app.
 | 
						|
 | 
						|
:marked
 | 
						|
  ## Template inline or template file?
 | 
						|
 | 
						|
  You can store your component's template in one of two places.
 | 
						|
  You can define it *inline* using the `template` property, or you can define
 | 
						|
  the template in a separate HTML file and link to it in
 | 
						|
  the component metadata using the `@Component` !{_decorator}'s `templateUrl` property.
 | 
						|
 | 
						|
  The choice between inline and separate HTML is a matter of taste,
 | 
						|
  circumstances, and organization policy.
 | 
						|
  Here the app uses inline HTML because the template is small and the demo
 | 
						|
  is simpler without the additional HTML file.
 | 
						|
 | 
						|
  In either style, the template data bindings have the same access to the component's properties.
 | 
						|
 | 
						|
+ifDocsFor('ts')
 | 
						|
  :marked
 | 
						|
    ## Constructor or variable initialization?
 | 
						|
 | 
						|
    Although this example uses variable assignment to initialize the components, you can instead declare and initialize the properties using a constructor:
 | 
						|
 | 
						|
  +makeExcerpt('app/app-ctor.component.ts', 'class')
 | 
						|
 | 
						|
  :marked
 | 
						|
    This app uses more terse "variable assignment" style simply for brevity.
 | 
						|
 | 
						|
.l-main-section#ngFor
 | 
						|
:marked
 | 
						|
  ## Showing !{_an} !{_array} property with ***ngFor**
 | 
						|
 | 
						|
  To display a list of heroes, begin by adding !{_an} !{_array} of hero names to the component and redefine `myHero` to be the first name in the !{_array}.
 | 
						|
 | 
						|
+makeExcerpt('app/app.component.2.ts', 'class')
 | 
						|
 | 
						|
:marked
 | 
						|
  Now use the Angular `ngFor` directive in the template to display
 | 
						|
  each item in the `heroes` list.
 | 
						|
 | 
						|
+makeExcerpt('app/app.component.2.ts', 'template')
 | 
						|
 | 
						|
:marked
 | 
						|
  This UI uses the HTML unordered list with `<ul>` and `<li>` tags. The `*ngFor`
 | 
						|
  in the `<li>` element is the Angular "repeater" directive.
 | 
						|
  It marks that `<li>` element (and its children) as the "repeater template":
 | 
						|
 | 
						|
+makeExcerpt('app/app.component.2.ts ()', 'li', '')
 | 
						|
 | 
						|
.alert.is-important
 | 
						|
  :marked
 | 
						|
    Don't forget the leading asterisk (\*) in `*ngFor`. It is an essential part of the syntax.
 | 
						|
    For more information, see the [Template Syntax](./template-syntax.html#ngFor) page.
 | 
						|
 | 
						|
:marked
 | 
						|
  Notice the `hero` in the `ngFor` double-quoted instruction;
 | 
						|
  it is an example of a template input variable. Read
 | 
						|
  more about template input variables in the [microsyntax](./template-syntax.html#ngForMicrosyntax) section of
 | 
						|
  the [Template Syntax](./template-syntax.html) page.
 | 
						|
 | 
						|
  Angular duplicates the `<li>` for each item in the list, setting the `hero` variable
 | 
						|
  to the item (the hero) in the current iteration. Angular uses that variable as the
 | 
						|
  context for the interpolation in the double curly braces.
 | 
						|
 | 
						|
.l-sub-section
 | 
						|
  :marked
 | 
						|
    In this case, `ngFor` is displaying !{_an} !{_array}, but `ngFor` can
 | 
						|
    repeat items for any [iterable](!{_iterableUrl}) object.
 | 
						|
:marked
 | 
						|
  Now the heroes appear in an unordered list.
 | 
						|
 | 
						|
figure.image-display
 | 
						|
  img(src="/resources/images/devguide/displaying-data/hero-names-list.png" alt="After ngfor")
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Creating a class for the data
 | 
						|
 | 
						|
  The app's code defines the data directly inside the component, which isn't best practice.
 | 
						|
  In a simple demo, however, it's fine.
 | 
						|
 | 
						|
  At the moment, the binding is to !{_an} !{_array} of strings.
 | 
						|
  In real applications, most bindings are to more specialized objects.
 | 
						|
 | 
						|
  To convert this binding to use specialized objects, turn the !{_array}
 | 
						|
  of hero names into !{_an} !{_array} of `Hero` objects. For that you'll need a `Hero` class.
 | 
						|
 | 
						|
  Create a new file in the `!{_appDir}` folder called  <ngio-ex path="hero.ts"></ngio-ex> with the following code:
 | 
						|
 | 
						|
+makeExcerpt('app/hero.ts')
 | 
						|
 | 
						|
block hero-class
 | 
						|
  :marked
 | 
						|
    You've defined a class with a constructor and two properties: `id` and `name`.
 | 
						|
 | 
						|
    It might not look like the class has properties, but it does.
 | 
						|
    The declaration of the constructor parameters takes advantage of a TypeScript shortcut.
 | 
						|
 | 
						|
    Consider the first parameter:
 | 
						|
 | 
						|
  +makeExcerpt('app/hero.ts ()', 'id')
 | 
						|
 | 
						|
  :marked
 | 
						|
    That brief syntax does a lot:
 | 
						|
    * Declares a constructor parameter and its type.
 | 
						|
    * Declares a public property of the same name.
 | 
						|
    * Initializes that property with the corresponding argument when creating an instance of the class.
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Using the Hero class
 | 
						|
 | 
						|
  The `heroes` property in the component can now use the `Hero` class to return !{_an} !{_array}
 | 
						|
  of `Hero` objects:
 | 
						|
 | 
						|
+makeExcerpt('app/app.component.3.ts', 'heroes')
 | 
						|
 | 
						|
:marked
 | 
						|
  Next, update the template.
 | 
						|
  At the moment it displays the hero's `id` and `name`.
 | 
						|
  Fix that to display only the hero's `name` property.
 | 
						|
 | 
						|
+makeExcerpt('app/app.component.3.ts', 'template')
 | 
						|
 | 
						|
:marked
 | 
						|
  The display looks the same, but the code is clearer.
 | 
						|
 | 
						|
.l-main-section#ngIf
 | 
						|
:marked
 | 
						|
  ## Conditional display with NgIf
 | 
						|
 | 
						|
  Sometimes an app needs to display a view or a portion of a view only under specific circumstances.
 | 
						|
 | 
						|
  Let's change the example to display a message if there are more than three heroes.
 | 
						|
 | 
						|
  The Angular `ngIf` directive inserts or removes an element based on a !{_boolean} condition.
 | 
						|
  To see it in action, add the following paragraph at the bottom of the template:
 | 
						|
 | 
						|
+makeExcerpt('app/app.component.ts', 'message')
 | 
						|
 | 
						|
.alert.is-important
 | 
						|
  :marked
 | 
						|
    Don't forget the leading asterisk (\*) in `*ngIf`. It is an essential part of the syntax.
 | 
						|
    Read more about `ngIf` and `*` in the [ngIf section](./template-syntax.html#ngIf) of the [Template Syntax](./template-syntax.html) page.
 | 
						|
 | 
						|
:marked
 | 
						|
  The template expression inside the double quotes,
 | 
						|
  `*ngIf="heros.length > 3"`, looks and behaves much like !{_Lang}.
 | 
						|
  When the component's list of heroes has more than three items, Angular adds the paragraph
 | 
						|
  to the DOM and the message appears. If there are three or fewer items, Angular omits the
 | 
						|
  paragraph, so no message appears. For more information,
 | 
						|
  see the [template expressions](./template-syntax.html#template-expressions) section of the
 | 
						|
  [Template Syntax](./template-syntax.html) page.
 | 
						|
 | 
						|
.alert.is-helpful
 | 
						|
  :marked
 | 
						|
    Angular isn't showing and hiding the message. It is adding and removing the paragraph element from the DOM. That improves performance, especially in larger projects when conditionally including or excluding
 | 
						|
    big chunks of HTML with many data bindings.
 | 
						|
 | 
						|
:marked
 | 
						|
  Try it out. Because the !{_array} has four items, the message should appear.
 | 
						|
  Go back into <ngio-ex path="app.component.ts"></ngio-ex> and delete or comment out one of the elements from the hero !{_array}.
 | 
						|
  The browser should refresh automatically and the message should disappear.
 | 
						|
 | 
						|
.l-main-section
 | 
						|
:marked
 | 
						|
  ## Summary
 | 
						|
  Now you know how to use:
 | 
						|
  - **Interpolation** with double curly braces to display a component property.
 | 
						|
  - **ngFor** to display !{_an} !{_array} of items.
 | 
						|
  - A !{_Lang} class to shape the **model data** for your component and display properties of that model.
 | 
						|
  - **ngIf** to conditionally display a chunk of HTML based on a boolean expression.
 | 
						|
 | 
						|
  Here's the final code:
 | 
						|
 | 
						|
block final-code
 | 
						|
  +makeTabs(`displaying-data/ts/app/app.component.ts,
 | 
						|
             displaying-data/ts/app/hero.ts,
 | 
						|
             displaying-data/ts/app/app.module.ts,
 | 
						|
             displaying-data/ts/app/main.ts`,
 | 
						|
             'final,,,',
 | 
						|
             'app/app.component.ts, app/hero.ts, app.module.ts, main.ts') |