diff --git a/aio/content/examples/forms/src/app/app.component.css b/aio/content/examples/forms/src/app/app.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/forms/src/app/app.component.html b/aio/content/examples/forms/src/app/app.component.html new file mode 100644 index 0000000000..84d14ff8f6 --- /dev/null +++ b/aio/content/examples/forms/src/app/app.component.html @@ -0,0 +1 @@ + diff --git a/aio/content/examples/forms/src/app/app.component.ts b/aio/content/examples/forms/src/app/app.component.ts index 4e48439924..f7baece9b5 100644 --- a/aio/content/examples/forms/src/app/app.component.ts +++ b/aio/content/examples/forms/src/app/app.component.ts @@ -3,6 +3,7 @@ import { Component } from '@angular/core'; @Component({ selector: 'app-root', - template: '' + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] }) export class AppComponent { } diff --git a/aio/content/examples/forms/src/app/app.module.ts b/aio/content/examples/forms/src/app/app.module.ts index f214c02714..51b9b9afe2 100644 --- a/aio/content/examples/forms/src/app/app.module.ts +++ b/aio/content/examples/forms/src/app/app.module.ts @@ -4,7 +4,7 @@ import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; -import { HeroFormComponent } from './hero-form.component'; +import { HeroFormComponent } from './hero-form/hero-form.component'; @NgModule({ imports: [ @@ -15,6 +15,7 @@ import { HeroFormComponent } from './hero-form.component'; AppComponent, HeroFormComponent ], + providers: [], bootstrap: [ AppComponent ] }) export class AppModule { } diff --git a/aio/content/examples/forms/src/app/hero-form/hero-form.component.css b/aio/content/examples/forms/src/app/hero-form/hero-form.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aio/content/examples/forms/src/app/hero-form.component.html b/aio/content/examples/forms/src/app/hero-form/hero-form.component.html similarity index 100% rename from aio/content/examples/forms/src/app/hero-form.component.html rename to aio/content/examples/forms/src/app/hero-form/hero-form.component.html diff --git a/aio/content/examples/forms/src/app/hero-form.component.ts b/aio/content/examples/forms/src/app/hero-form/hero-form.component.ts similarity index 92% rename from aio/content/examples/forms/src/app/hero-form.component.ts rename to aio/content/examples/forms/src/app/hero-form/hero-form.component.ts index bfc290b5a3..bc5fe12ef8 100644 --- a/aio/content/examples/forms/src/app/hero-form.component.ts +++ b/aio/content/examples/forms/src/app/hero-form/hero-form.component.ts @@ -2,11 +2,12 @@ // #docregion , v1, final import { Component } from '@angular/core'; -import { Hero } from './hero'; +import { Hero } from '../hero'; @Component({ selector: 'app-hero-form', - templateUrl: './hero-form.component.html' + templateUrl: './hero-form.component.html', + styleUrls: ['./hero-form.component.css'] }) export class HeroFormComponent { diff --git a/aio/content/examples/forms/src/styles.1.css b/aio/content/examples/forms/src/styles.1.css new file mode 100644 index 0000000000..167a66be4f --- /dev/null +++ b/aio/content/examples/forms/src/styles.1.css @@ -0,0 +1 @@ +@import url('https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css'); diff --git a/aio/content/guide/forms.md b/aio/content/guide/forms.md index 8731b34d73..94e337c0a2 100644 --- a/aio/content/guide/forms.md +++ b/aio/content/guide/forms.md @@ -29,19 +29,13 @@ You can run the in Plunker and download the code f You can build forms by writing templates in the Angular [template syntax](guide/template-syntax) with the form-specific directives and techniques described in this page. -
- - -You can also use a reactive (or model-driven) approach to build forms. -However, this page focuses on template-driven forms. - + You can also use a reactive (or model-driven) approach to build forms. + However, this page focuses on template-driven forms.
- - You can build almost any form with an Angular template—login forms, contact forms, and pretty much any business form. You can lay out the controls creatively, bind them to data, specify validation rules and display validation errors, conditionally enable or disable specific controls, trigger built-in visual feedback, and much more. @@ -51,13 +45,10 @@ otherwise wrestle with yourself. You'll learn to build a template-driven form that looks like this: -
Clean Form
- - The *Hero Employment Agency* uses this form to maintain personal information about heroes. Every hero needs a job. It's the company mission to match the right hero with the right crisis. @@ -65,27 +56,18 @@ Two of the three fields on this form are required. Required fields have a green If you delete the hero name, the form displays a validation error in an attention-grabbing style: -
Invalid, Name Required
- - Note that the *Submit* button is disabled, and the "required" bar to the left of the input control changes from green to red. -
- - -You can customize the colors and location of the "required" bar with standard CSS. - + You can customize the colors and location of the "required" bar with standard CSS.
- - You'll build this form in small steps: 1. Create the `Hero` model class. @@ -98,11 +80,15 @@ You'll build this form in small steps: 1. Handle form submission with *ngSubmit*. 1. Disable the form’s *Submit* button until the form is valid. - ## Setup -Follow the [setup](guide/setup) instructions for creating a new project -named angular-forms. +Create a new project named angular-forms: + + + + ng new angular-forms + + ## Create the Hero model class @@ -113,15 +99,20 @@ A model can be as simple as a "property bag" that holds facts about a thing of a That describes well the `Hero` class with its three required fields (`id`, `name`, `power`) and one optional field (`alterEgo`). -In the `app` directory, create the following file with the given content: +Using the Angular CLI, generate a new class named `Hero`: + + + ng generate class Hero + + + +With this content: - - It's an anemic model with few requirements and no behavior. Perfect for the demo. The TypeScript compiler generates a public field for each `public` constructor parameter and @@ -131,28 +122,29 @@ The `alterEgo` is optional, so the constructor lets you omit it; note the questi You can create a new hero like this: - - + - - - ## Create a form component An Angular form has two parts: an HTML-based _template_ and a component _class_ to handle data and user interactions programmatically. Begin with the class because it states, in brief, what the hero editor can do. -Create the following file with the given content: +Using the Angular CLI, generate a new component named `HeroForm`: + - + ng generate component HeroForm +With this content: + + + There’s nothing special about this component, nothing form-specific, nothing to distinguish it from any component you've written before. @@ -173,21 +165,6 @@ parent component. This is not a concern now and these future changes won't affec * You added a `diagnostic` property to return a JSON representation of the model. It'll help you see what you're doing during development; you've left yourself a cleanup note to discard it later. -### Why the separate template file? - -Why don't you write the template inline in the component file as you often do elsewhere? - -There is no "right" answer for all occasions. Inline templates are useful when they are short. -Most form templates aren't short. TypeScript and JavaScript files generally aren't the best place to -write (or read) large stretches of HTML, and few editors help with files that have a mix of HTML and code. - -Form templates tend to be large, even when displaying a small number of fields, -so it's usually best to put the HTML template in a separate file. -You'll write that template file in a moment. First, -revise the `app.module.ts` and `app.component.ts` to make use of the new `HeroFormComponent`. - - - ## Revise *app.module.ts* `app.module.ts` defines the application's root module. In it you identify the external modules you'll use in the application @@ -196,89 +173,57 @@ and declare the components that belong to this module, such as the `HeroFormComp Because template-driven forms are in their own module, you need to add the `FormsModule` to the array of `imports` for the application module before you can use forms. -Replace the contents of the "QuickStart" version with the following: +Update it with the following: - - - -
+ There are two changes: + 1. You import `FormsModule`. -There are three changes: - -1. You import `FormsModule` and the new `HeroFormComponent`. - -1. You add the `FormsModule` to the list of `imports` defined in the `@NgModule` decorator. This gives the application -access to all of the template-driven forms features, including `ngModel`. - -1. You add the `HeroFormComponent` to the list of `declarations` defined in the `@NgModule` decorator. This makes -the `HeroFormComponent` component visible throughout this module. - + 1. You add the `FormsModule` to the list of `imports` defined in the `@NgModule` decorator. This gives the application + access to all of the template-driven forms features, including `ngModel`.
- -
- - -If a component, directive, or pipe belongs to a module in the `imports` array, ​_don't_​ re-declare it in the `declarations` array. -If you wrote it and it should belong to this module, ​_do_​ declare it in the `declarations` array. - + If a component, directive, or pipe belongs to a module in the `imports` array, ​_don't_​ re-declare it in the `declarations` array. + If you wrote it and it should belong to this module, ​_do_​ declare it in the `declarations` array.
- - - -## Revise *app.component.ts* +## Revise *app.component.html* `AppComponent` is the application's root component. It will host the new `HeroFormComponent`. -Replace the contents of the "QuickStart" version with the following: +Replace the contents of its template with the following: - - + - - - -
- - -There are only two changes. -The `template` is simply the new element tag identified by the component's `selector` property. -This displays the hero form when the application component is loaded. -You've also dropped the `name` field from the class body. - + There are only two changes. + The `template` is simply the new element tag identified by the component's `selector` property. + This displays the hero form when the application component is loaded. + Don't forget to remove the `name` field from the class body as well.
- - - ## Create an initial HTML form template -Create the template file with the following contents: +Update the template file with the following contents: - - + - - The language is simply HTML5. You're presenting two of the `Hero` fields, `name` and `alterEgo`, and opening them up for user input in input boxes. @@ -289,52 +234,34 @@ You added a *Submit* button at the bottom with some classes on it for styling. *You're not using Angular yet*. There are no bindings or extra directives, just layout. -
- - -In template driven forms, if you've imported `FormsModule`, you don't have to do anything -to the `
` tag in order to make use of `FormsModule`. Continue on to see how this works. - + In template driven forms, if you've imported `FormsModule`, you don't have to do anything + to the `` tag in order to make use of `FormsModule`. Continue on to see how this works.
- - The `container`, `form-group`, `form-control`, and `btn` classes come from [Twitter Bootstrap](http://getbootstrap.com/css/). These classes are purely cosmetic. Bootstrap gives the form a little style. -
+
+ Angular forms don't require a style library +
- -
- Angular forms don't require a style library -
- - - -Angular makes no use of the `container`, `form-group`, `form-control`, and `btn` classes or -the styles of any external library. Angular apps can use any CSS library or none at all. - + Angular makes no use of the `container`, `form-group`, `form-control`, and `btn` classes or + the styles of any external library. Angular apps can use any CSS library or none at all.
+To add the stylesheet, open `styles.css` and add the following import line at the top: - -To add the stylesheet, open `index.html` and add the following link to the ``: - - - + - - - ## Add powers with _*ngFor_ The hero must choose one superpower from a fixed list of agency-approved powers. @@ -346,13 +273,10 @@ a technique seen previously in the [Displaying Data](guide/displaying-data) page Add the following HTML *immediately below* the *Alter Ego* group: - - + - - This code repeats the `