<!-- #docregion my-first-app --> <h3>My First Angular Application</h3> <!-- #enddocregion my-first-app --> <!-- Interpolation and expressions --> <hr><h2>Interpolation</h2> <!-- #docregion first-interpolation --> <p>My current hero is {{currentHero.firstName}}</p> <!-- #enddocregion first-interpolation --> <!-- #docregion title+image --> <h3> {{title}} <img src="{{heroImageUrl}}" style="height:30px"> </h3> <!-- #enddocregion title+image --> <!-- #docregion sum-1 --> <!-- "The sum of 1 + 1 is 2" --> <p>The sum of 1 + 1 is {{1 + 1}}</p> <!-- #enddocregion sum-1 --> <!-- #docregion sum-2 --> <!-- "The sum of 1 + 1 is not 4" --> <p>The sum of 1 + 1 is not {{1 + 1 + getVal}}</p> <!-- #enddocregion sum-2 --> <!-- New Mental Model --> <hr><h2>New Mental Model</h2> <!--<img src="http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png">--> <!-- Public Domain terms of use: http://www.wpclipart.com/terms.html --> <!-- #docregion img+button --> <div class="special">Mental Model</div> <div><b>{{currentHero.fullName}}</b></div> <img src="assets/images/hero.png"> <button disabled>Save</button> <!-- #enddocregion img+button --> <br><br> <div> <!-- #docregion hero-detail-1 --> <div class="special">Mental Model</div> <hero-detail></hero-detail> <!-- #enddocregion hero-detail-1 --> </div> <br><br> <div> <!-- #docregion disabled-button-1 --> <!-- Bind button disabled state to `isUnchanged` property --> <button [disabled]="isUnchanged">Save</button> <!-- #enddocregion disabled-button-1 --> </div> <br><br> <div> <!-- #docregion property-binding-syntax-1 --> <img [src] = "heroImageUrl"> <hero-detail [hero]="currentHero"></hero-detail> <div [ngClass] = "{selected: isSelected}"></div> <!-- #enddocregion property-binding-syntax-1 --> </div> <br><br> <!-- See https://github.com/angular/angular/issues/5707 about "myClick (myClick)" --> <!-- #docregion event-binding-syntax-1 --> <button (click) = "onSave()">Save</button> <hero-detail (deleted)="onHeroDeleted()"></hero-detail> <div myClick (myClick)="clicked=$event">click me</div> <!-- #enddocregion event-binding-syntax-1 --> <!-- {{clicked}} --> <!-- causes exception in Dart version --> <br><br> <div> <!-- #docregion 2-way-binding-syntax-1 --> <input [(ngModel)]="heroName"> <!-- #enddocregion 2-way-binding-syntax-1 --> Hero Name: {{heroName}} </div> <br><br> <!-- #docregion attribute-binding-syntax-1 --> <button [attr.aria-label]="help">help</button> <!-- #enddocregion attribute-binding-syntax-1 --> <br><br> <!-- #docregion class-binding-syntax-1 --> <div [class.special]="isSpecial">Special</div> <!-- #enddocregion class-binding-syntax-1 --> <br><br> <!-- #docregion style-binding-syntax-1 --> <button [style.color] = "isSpecial ? 'red' : 'green'"> <!-- #enddocregion style-binding-syntax-1 --> button</button> <!-- property vs. attribute --> <hr><h2>Property vs. Attribute (img examples)</h2> <!-- examine the following <img> tag in the browser tools --> <img src="assets/images/ng-logo.png" [src]="heroImageUrl"> <br><br> <img [src]="iconUrl"/> <img bind-src="heroImageUrl"/> <img [attr.src]="villainImageUrl"/> <!-- buttons --> <hr><h2>Buttons</h2> <button>Enabled (but does nothing)</button> <button disabled>Disabled</button> <button disabled=false>Still disabled</button> <br><br> <button disabled>disabled by attribute</button> <button [disabled]="isUnchanged">disabled by property binding</button> <br><br> <button bind-disabled="isUnchanged" on-click="onSave($event)">Disabled Cancel</button> <button [disabled]="!canSave" (click)="onSave($event)">Enabled Save</button> <!-- property binding --> <hr><h2>Property Binding</h2> <!-- #docregion property-binding-1 --> <img [src]="heroImageUrl"> <!-- #enddocregion property-binding-1 --> <!-- #docregion property-binding-2 --> <button [disabled]="isUnchanged">Cancel</button> <!-- #enddocregion property-binding-2 --> <!-- #docregion property-binding-3 --> <div [ngClass]="'special'">NgClass is special</div> <!-- #enddocregion property-binding-3 --> <!-- #docregion property-binding-4 --> <hero-detail [hero]="selectedHero"></hero-detail> <!-- #enddocregion property-binding-4 --> <!-- #docregion property-binding-5 --> <img bind-src="heroImageUrl"> <!-- #enddocregion property-binding-5 --> <!-- #docregion property-binding-6 --> <!-- Doesn't work! HeroDetailComponent expects a Hero, not a string --> <!--<hero-detail hero="…what do we do here??? …"></hero-detail>--> <!--THROWS ERROR IN DART--> <!-- #enddocregion property-binding-6 --> <!-- #docregion property-binding-vs-interpolation --> <img src="{{heroImageUrl}}"> <img [src]="'' + heroImageUrl"> <div>The title is {{title}}</div> <div [textContent]="'The title is '+title"></div> <!-- #enddocregion property-binding-vs-interpolation --> <!-- attribute binding --> <hr><h2>Attribute Binding</h2> <!-- create and set a colspan attribute --> <!-- #docregion attrib-binding-colspan --> <table border=1> <!-- expression calculates colspan=2 --> <tr><td [attr.colspan]="1 + 1">One-Two</td></tr> <!-- ERROR: There is no `colspan` property to set! <tr><td colspan="{{1 + 1}}">Three-Four</td></tr> --> <tr><td>Five</td><td>Six</td></tr> </table> <!-- #enddocregion attrib-binding-colspan --> <br> <!-- #docregion attrib-binding-aria --> <!-- create and set an aria attribute for assistive technology --> <button [attr.aria-label]="actionName">{{actionName}} with Aria</button> <!-- #enddocregion attrib-binding-aria --> <br><br> <!-- The following effects are not discussed in the chapter --> <div> <!-- any use of [attr.disabled] creates the disabled attribute --> <button [attr.disabled]="isUnchanged">Disabled</button> <button [attr.disabled]="!isUnchanged">Disabled as well</button> <!-- can't remove it with [attr.disabled] either --> <button disabled [attr.disabled]>Still disabled</button> <!-- we'd have to remove it with property binding --> <button disabled [disabled]="false">Enabled (but inert)</button> </div> <!-- class binding --> <hr><h2>Class Binding</h2> <!-- #docregion class-binding-1 --> <!-- standard class attribute setting --> <div class="bad curly special">Bad curly special</div> <!-- #enddocregion class-binding-1 --> <!-- #docregion class-binding-2 --> <!-- reset all class names with a string binding --> <div class="bad curly special" [class]="'bad curly'">Bad curly</div> <!-- #enddocregion class-binding-2 --> <!-- #docregion class-binding-3 --> <!-- #docregion class-binding-3a --> <!-- toggle the "special" class on/off with a property --> <div [class.special]="isSpecial">The class binding is special</div> <!-- #enddocregion class-binding-3a --> <!-- binding to `class.special` trumps the class attribute --> <div class="special" [class.special]="!isSpecial">This one is not so special</div> <!-- #enddocregion class-binding-3 --> <div bind-class.special="isSpecial">This class binding is special too</div> <!--style binding --> <hr><h2>Style Binding</h2> <!-- #docregion style-binding-1 --> <button [style.color] = "isSpecial ? 'red': 'green'">Red</button> <button [style.background-color]="canSave ? 'cyan': 'grey'" >Save</button> <!-- #enddocregion style-binding-1 --> <!-- #docregion style-binding-2 --> <button [style.font-size.em]="isSpecial ? 3 : 1" >Big</button> <button [style.font-size.%]="!isSpecial ? 150 : 50" >Small</button> <!-- #enddocregion style-binding-2 --> <!-- event binding --> <hr><h2>Event Binding</h2> <!-- #docregion event-binding-1 --> <button (click)="onSave()">Save</button> <!-- #enddocregion event-binding-1 --> <!-- #docregion event-binding-2 --> <button on-click="onSave()">On Save</button> <!-- #enddocregion event-binding-2 --> <div> <!-- #docregion event-binding-3 --> <!-- `myClick` is an event on the custom `MyClickDirective` --> <!-- #docregion my-click --> <div myClick (myClick)="clickity=$event">click with myClick</div> <!-- #enddocregion my-click --> <!-- #enddocregion event-binding-3 --> {{clickity}} </div> <!-- binding to a nested component --> <!-- #docregion event-binding-to-component --> <hero-detail (deleted)="onHeroDeleted($event)" [hero]="currentHero"> </hero-detail> <!-- #enddocregion event-binding-to-component --> <br> <big-hero-detail (deleted)="onHeroDeleted($event)" [hero]="currentHero"> </big-hero-detail> <!-- #docregion event-binding-bubbling --> <div class="parent-div" (click)="onClickMe($event)">Click me <div class="child-div">Click me too!</div> </div> <!-- #enddocregion event-binding-bubbling --> <br><br> <!-- #docregion event-binding-no-propagation --> <!-- Will save only once --> <div (click)="onSave()"> <button (click)="onSave()">Save, no propagation</button> </div> <!-- #enddocregion event-binding-no-propagation --> <br><br> <!-- #docregion event-binding-propagation --> <!-- Will save twice --> <div (click)="onSave()"> <button (click)="onSave() || true">Save w/ propagation</button> </div> <!-- #enddocregion event-binding-propagation --> <br><br> <!-- Two way data binding unwound; passing the changed display value to the event handler via `$event` --> <hr><h2>NgModel Binding</h2> <h3>Result: {{currentHero.firstName}}</h3> <!-- #docregion without-NgModel --> <input [value]="currentHero.firstName" (input)="currentHero.firstName=$event.target.value" > <!-- #enddocregion without-NgModel --> without NgModel <br> <!-- #docregion NgModel-1 --> <input [(ngModel)]="currentHero.firstName"> <!-- #enddocregion NgModel-1 --> [(ngModel)] <br> <!-- #docregion NgModel-2 --> <input bindon-ngModel="currentHero.firstName"> <!-- #enddocregion NgModel-2 --> bindon-ngModel <br> <!-- #docregion NgModel-3 --> <input [ngModel]="currentHero.firstName" (ngModelChange)="currentHero.firstName=$event"> <!-- #enddocregion NgModel-3 --> (ngModelChange) = "...firstName=$event" <br> <!-- #docregion NgModel-4 --> <input [ngModel]="currentHero.firstName" (ngModelChange)="setUpperCaseFirstName($event)"> <!-- #enddocregion NgModel-4 --> (ngModelChange) = "setUpperCaseFirstName($event)" <br> <!-- NgClass binding --> <hr><h2>NgClass Binding</h2> <p>setClasses returns {{setClasses() | json}}</p> <!-- #docregion NgClass-1 --> <div [ngClass]="setClasses()">This div is saveable and special</div> <!-- #enddocregion NgClass-1 --> <div [ngClass]="setClasses()" #classDiv> After setClasses(), the classes are "{{classDiv.className}}" </div> <!-- not used in chapter --> <div [ngClass]="isSpecial ? 'special' : ''">This div is special</div> <div class="bad curly special">Bad curly special</div> <div [ngClass]="{bad:false, curly:true, special:true}">Curly special</div> <!-- NgStyle binding --> <hr><h2>NgStyle Binding</h2> <!-- #docregion NgStyle-1 --> <div [style.font-size]="isSpecial ? 'x-large' : 'smaller'" > This div is x-large </div> <!-- #enddocregion NgStyle-1 --> <h3>Use setStyles() - CSS property names</h3> <p>setStyles returns {{setStyles() | json}}</p> <!-- #docregion NgStyle-2 --> <div [ngStyle]="setStyles()"> This div is italic, normal weight, and x-large </div> <!-- #enddocregion NgStyle-2 --> <div [ngStyle]="setStyles()" #styleDiv> After setStyles(), the styles are "{{getStyles(styleDiv)}}" </div> <h3>Use setStyles2() - camelCase style property names</h3> <p>setStyles2 returns {{setStyles2() | json}}</p> <!-- #docregion NgStyle-3 --> <div [ngStyle]="setStyles2()"> This div is italic, normal weight, and x-large </div> <!-- #enddocregion NgStyle-3 --> <div [ngStyle]="setStyles2()" #styleDiv2> After setStyles2(), the styles are "{{getStyles(styleDiv2)}}" </div> <!-- not used in chapter --> <!-- NgIf binding --> <hr><h2>NgIf Binding</h2> <!-- #docregion NgIf-1 --> <div *ngIf="currentHero != null">Hello, {{currentHero.firstName}}</div> <!-- #enddocregion NgIf-1 --> <!-- #docregion NgIf-2 --> <!-- not displayed because nullHero is falsey. `nullHero.firstName` never has a chance to fail --> <div *ngIf="nullHero != null">Hello, {{nullHero.firstName}}</div> <!-- Hero Detail is not in the DOM because isActive is false--> <hero-detail *ngIf="isActive"></hero-detail> <!-- #enddocregion NgIf-2 --> <!-- NgIf binding with template (no *) --> <template [ngIf]="currentHero != null">Add {{currentHero.firstName}} with template</template> <!-- Does not show because isActive is false! --> <div>Hero Detail removed from DOM (via template) because isActive is false</div> <template [ngIf]="isActive"> <hero-detail></hero-detail> </template> <!-- #docregion NgIf-3 --> <!-- isSpecial is true --> <div [class.hidden]="!isSpecial">Show with class</div> <div [class.hidden]="isSpecial">Hide with class</div> <!-- HeroDetail is in the DOM but hidden --> <hero-detail [class.hidden]="isSpecial"></hero-detail> <div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div> <div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div> <!-- #enddocregion NgIf-3 --> <!-- NgSwitch binding --> <hr><h2>NgSwitch Binding</h2> <fieldset #toePicker (click)="toeChooser(toePicker)" > <input type="radio" name="toes" value="Eenie">Eenie <input type="radio" name="toes" value="Meanie">Meanie <input type="radio" name="toes" value="Miney">Miney <input type="radio" name="toes" value="Moe">Moe <input type="radio" name="toes" value="???">??? </fieldset> <div class="toe"> <div *ngIf="chosenToe == null">Pick a toe</div> <div *ngIf="chosenToe != null">You picked <!-- #docregion NgSwitch --> <span [ngSwitch]="chosenToe"> <template [ngSwitchWhen]="'Eenie'">Eenie</template> <template [ngSwitchWhen]="'Meanie'">Meanie</template> <template [ngSwitchWhen]="'Miney'">Miney</template> <template [ngSwitchWhen]="'Moe'">Moe</template> <template ngSwitchDefault>Other</template> </span> <!-- #enddocregion NgSwitch --> </div> </div> <!-- NgFor binding --> <hr><h2>NgFor Binding</h2> <div class="box"> <!-- #docregion NgFor-1 --> <div *ngFor="#hero of heroes">{{hero.fullName}}</div> <!-- #enddocregion NgFor-1 --> </div> <br> <div class="box"> <!-- *ngFor w/ hero-detail Component --> <!-- #docregion NgFor-2 --> <hero-detail *ngFor="#hero of heroes" [hero]="hero"></hero-detail> <!-- #enddocregion NgFor-2 --> </div> <br> <div class="box"> <!-- #docregion NgFor-3 --> <!-- Ex: 1 - Hercules Son of Zeus --> <div *ngFor="#hero of heroes, #i=index">{{i + 1}} - {{hero.fullName}}</div> <!-- #enddocregion NgFor-3 --> </div> <br> <!-- * and template --> <hr><h2>* and Template</h2> <h3>NgIf expansion</h3> <!-- #docregion Template-1 --> <hero-detail *ngIf="currentHero != null" [hero]="currentHero"></hero-detail> <!-- #enddocregion Template-1 --> <!-- #docregion Template-2 --> <template [ngIf]="currentHero != null"> <hero-detail [hero]="currentHero"></hero-detail> </template> <!-- #enddocregion Template-2 --> <h3>NgFor expansion</h3> <div class="box"> <!-- ngFor w/ hero-detail Component and a template "attribute" directive --> <!-- #docregion Template-3 --> <hero-detail template="ngFor #hero of heroes" [hero]="hero"></hero-detail> <!-- #enddocregion Template-3 --> </div> <br> <div class="box"> <!-- ngFor w/ hero-detail Component inside a template element --> <!-- #docregion Template-4 --> <template ngFor #hero [ngForOf]="heroes"> <hero-detail [hero]="hero"></hero-detail> </template> <!-- #enddocregion Template-4 --> </div> <!-- template local variable --> <hr><h2>Template local variables</h2> <!-- #docregion var-phone --> <!-- phone refers to the input element; pass its `value` to an event handler --> <input #phone placeholder="phone number"> <button (click)="callPhone(phone.value)">Call</button> <!-- fax refers to the input element; pass its `value` to an event handler --> <input var-fax placeholder="phone number"> <button (click)="callFax(fax.value)">Fax</button> <!-- #enddocregion var-phone --> <h4>Example Form</h4> <!-- #docregion var-form --> <!-- #docregion var-form-a --> <form (ngSubmit)="onSubmit(theForm)" #theForm="ngForm"> <!-- #enddocregion var-form-a --> <div class="form-group"> <label for="name">Name</label> <input id="name" class="form-control" required ngControl="firstName" [(ngModel)]="currentHero.firstName"> </div> <!-- #docregion var-form-a --> <button type="submit" [disabled]="!theForm.form.valid">Submit</button> </form> <!-- #enddocregion var-form-a --> <!-- #enddocregion var-form --> <br><br> <!-- btn refers to the button element; show its disabled state --> <button #btn disabled [textContent]="'disabled by attribute: ' + btn.disabled.toString()"></button> <!-- inputs and output --> <hr><h2>Inputs and Outputs</h2> <!-- #docregion io-1 --> <img [src]="iconUrl"/> <button (click)="onSave()">Save</button> <!-- #enddocregion io-1 --> <!-- #docregion io-2 --> <hero-detail [hero]="currentHero" (deleted)="onHeroDeleted($event)"> </hero-detail> <!-- #enddocregion io-2 --> <!-- <div myClick2 (myClick)="clicked2=$event">myClick2</div> {{clicked2}} PENDING: I don't see clicked2 defined anywhere in the TS example --> <!-- Pipes --> <hr><h2>Pipes</h2> <!-- #docregion pipes-1 --> <!-- Force title to uppercase --> <div>{{ title | uppercase }}</div> <!-- #enddocregion pipes-1 --> <!-- #docregion pipes-2 --> <!-- Pipe chaining: force title to uppercase, then to lowercase --> <div>{{ title | uppercase | lowercase }}</div> <!-- #enddocregion pipes-2 --> <!-- #docregion pipes-3 --> <!-- pipe with configuration argument => "February 25, 1970" --> <div>Birthdate: {{currentHero?.birthdate | date:'longDate'}}</div> <!-- #enddocregion pipes-3 --> <!-- #docregion pipes-json --> <!--<div>{{currentHero | json}}</div>--> <!-- PENDING: uncomment? --> <!-- Output: { "firstName": "Hercules", "lastName": "Son of Zeus", "birthdate": "1970-02-25T08:00:00.000Z", "url": "http://www.imdb.com/title/tt0065832/", "rate": 325, "id": 1 } --> <!-- #enddocregion pipes-json --> <div>Birthdate: {{(currentHero?.birthdate | date:'longDate') | uppercase}}</div> <div> <!-- pipe price to USD and display the $ symbol --> <!--<label>Price: </label>{{product.price | currency:'USD':true}}--> <!-- PENDING: uncomment? --> </div> <!-- Null values and the Elvis operator --> <hr><h2>Elvis</h2> <div> <!-- #docregion elvis-1 --> The title is {{ title }} <!-- #enddocregion elvis-1 --> </div> <div> <!-- #docregion elvis-2 --> The current hero's name is {{currentHero?.firstName}} <!-- #enddocregion elvis-2 --> </div> <div> <!-- #docregion elvis-3 --> The current hero's name is {{currentHero.firstName}} <!-- #enddocregion elvis-3 --> </div> <!-- The null hero's name is {{nullHero.firstName}} See console log TypeError: Cannot read property 'firstName' of null in [null] --> <!-- #docregion elvis-4 --> <!--No hero, div not displayed, no error --> <div *ngIf="nullHero != null">The null hero's name is {{nullHero.firstName}}</div> <!-- #enddocregion elvis-4 --> <div> <!-- #docregion elvis-5 --> The null hero's name is {{nullHero != null && nullHero.firstName != null}} <!-- PENDING: ??? --> <!-- #enddocregion elvis-5 --> </div> <div> <!-- #docregion elvis-6 --> <!-- No hero, no problem! --> The null hero's name is {{nullHero?.firstName}} <!-- #enddocregion elvis-6 --> </div> <!-- Todo: discuss this in the Style binding section --> <!-- enums in bindings --> <hr><h2>Enums in binding</h2> <p>The name of the Color.Red enum is {{color}}</p> <!-- PENDING: Color[Color.Red]?? --> <p>The current color number is {{color}}</p> <p><button [style.color]="color" (click)="colorToggle()">Enum Toggle</button> <!-- PENDING: color -> Color[color]? -->