Angular From Scratch Tutorial – Index
PREVIOUS: Angular From Scratch Tutorial – Step 2: Components
NEXT: Angular From Scratch Tutorial – Step 4: Adding Bootstrap
Table of Contents
TARGET
The purpose of this page in this tutorial series is to provide a very fast approach that is useful for revisions when you have already dealt with Angular, but after an absense of using it, it turns necessary to do a “disk swap” bringing from “disk” to your “memory” again. 🙂
If it is your first Angular approach, or you are a newbie, it is recommended to go first to the Angular’s documentation. After, this page will serve you as a summary for fast referencing and revision.
CONVENTIONS
About the notation adopted in this project.
The code created for this project has an “app” prefix.
Code, projects, implementations in general from external sources hasn’t this prefix.
SUMMARY
Binding is a key interaction concept.
It must be kept in mind the several ways it may occur.
This tutorial basically summarizes Angular documentation.
Useful for fast revisions.
TARGET
Binding handling.
Providing routing to the moved content creating a link to it.
Source Code/Download
For more details, the source code may be found on GitHub, “step3” tag (includes step1 up to step3).
DATA BINDING
Data Binding allows apps to display data values to a user and respond to user actions (such as clicks, touches, and keystrokes).
Forms of binding in Angular’s Template Syntax
- Interpolation
- Property binding
- Event binding
- Attribute binding
- Class and style binding
- Style binding
- Two-way data binding with ngModel
@FROM: Angular documentation
TARGET FOR THIS STEP
Implementation of data binding types.
SOURCE CODE
Since this step includes additional files, to make easier its implementation, the respective source code may be cloned from GitHub.
How to Use
The master branch contains the last current version.
To get this step (step3), do:
- Get a list of all available local tags (your machine):
git tag - Get a list of all available remote tags (on GitHub’s server).:
git ls-remote –tags origin - To checkout the step3 tag:
git checkout tags/step3
INTERPOLATION
Edit “app.component.html” to add title, setting it like this:
The title’s value comes from “app.component.ts”:
Test
http://localhost:4200/
Interpolation is simple like that.
It is used a double curl brace in the HTML file for a class property defined in the .ts file.
PROPERTY BINDING
To bind to an element’s property, enclose it in square brackets, []
, which identifies the property as a target property.
A target property is the DOM property to which you want to assign a value.
The brackets, []
, cause Angular to evaluate the right-hand side of the assignment as a dynamic expression.
Without the brackets, Angular treats the right-hand side as a string literal and sets the property to that static value.
[Angular documentation]
Binding a property
Edit “app.component.ts” and create the siteBadge property as follows:
export class AppComponent { title = 'afsTutorial'; siteBadge = '../assets/img/afstutorial_main_image.jpg'; }
Bind it to the HTML file (app.component.html):
<h2>{{title}}</h2> <img [src]="siteBadge"> <router-outlet></router-outlet>
Point to the main page:
http://localhost:4200/
DOM’s element property interpolation
When the page loads, the “carSelection.value” is “Fiat” by default.
If the selection is switched, it won’t switch the “carSelection.value” because it is necessary to assign an event that performs the update.
<h4>DOM's element property interpolation without event treatment</h4> <p> {{carSelection.value}} </p> <select #carSelection> <option value="Fiat">Fiat</option> <option value="Hyundai">Hyundai</option> <option value="Mercedes">Mercedes</option> </select>
DOM’s element property interpolation plus event
To make it dynamic just add to the select element the following:
(input)="0"
<h4>DOM's element property interpolation plus event</h4> <p> {{carSelection2.value}} </p> <select #carSelection2 (input)="0"> <option value="Fiat">Fiat</option> <option value="Hyundai">Hyundai</option> <option value="Mercedes">Mercedes</option> </select>
Binding to a DOM’s element property
Suppose you’re working with legacy code(very common, by the way), and you need to handle dynamically some attribute of a table’s row.
For instance, we may suppose the following alternatives:
CASE 1: The snippet below is a static interpolation that may be replaced by property binding to turn into a dynamic interpolation or binding.
Notice that it must be used the element’s property native name that uses camel case (span) and not something different from that like “Span”.
<tr><td span="{{1 + 1}}">Three-Four</td></tr>
CASE 2: Using the element’s binding and the property binding together:
Supposing that the app.component.ts file has span attribute as follows:
export class AppComponent { title = 'afsTutorial'; siteBadge = '../assets/img/afstutorial_main_image.jpg'; span = 3; }
The full HTML code (app.component.html) becomes:
<br /> <br /> <h4>[span]="1 + 1"</h4> <table> <colgroup> <col [span]="1 + 1" style="background-color:#D2D2D2"> </colgroup> <tr> <th>ISBN</th> <th>Title</th> <th>Price</th> </tr> <tr> <td>3476900</td> <td>Angular for Tomorrow</td> <td>$106</td> </tr> </table> <br /> <br /> <h4>[span]="span"</h4> <table> <colgroup> <col [span]="span" style="background-color:#D2D2D2"> </colgroup> <tr> <th>ISBN</th> <th>Title</th> <th>Price</th> </tr> <tr> <td>3476999</td> <td>Angular Forever</td> <td>$10600</td> </tr> </table>
Button’s Property Binding Example
- The HTML code in .html file: <button [disabled]="buttonDisabled"></button> - The JavaScript code for the class property in the respective .ts file: buttonDisabled = true;
Example using an image
app.component.html:
<h4>Property Binding Example Using an Image </h4> <h5> <img [alt]="birds[0].name" [src]="birds[0].image" /> </h5> <img [alt]="birds[0].name" [src]="birds[0].image" /> <br /><br /> <h5> <img bind-alt="birds[1].name" bind-src="birds[1].image"> </h5> <img bind-alt="birds[1].name" bind-src="birds[1].image"> <br /><br />
app.component.ts:
birds = [{
name: ‘Eagle #1’,
image: ‘../assets/img/eagle1.jpg’
}, {
name: ‘Eagle #2’,
image: ‘../assets/img/eagle2.jpg’
}];
Example handling an element’s property
app.component.html:
app.component.ts:
Other Examples
WRONG: the new operator:
<p> {{ new Date() }} </p>
Also, not allowed JavaScript expressions that have side effects:
like containing =, +=, -=, etc.
Operators: instanceOf, typeOf, for, while, etc.
Chaining statements using ‘;’ or ‘,’
Increment and decrement expressions like ++ and —
RIGHT
.html file:
<p> {{ convertToDate() }} </p>
.ts file:
function convertToDate(){ const date = new Date(); return date.toLocaleDateString(); }
Working with CSS
app.component.html:
<h4>CSS style using [ngStyle]</h4> <p [ngStyle]="pHighlight">TITLE HIGHLIGHTED #1</p><br /> <p [ngStyle]="pHighlight">TITLE HIGHLIGHTED #1</p> <br /><br /> <h4>CSS style not using [ngStyle]</h4> <p [style.color]="thColor" [style.font-size]="thFontSz" [style.background]="thBackground">TITLE HIGHLIGHTED #2</p><br /> <p [style.color]="thColor" [style.font-size]="thFontSz" [style.background]="thBackground">TITLE HIGHLIGHTED #2</p> <br /><br />
app.component.ts:
pHighlight = { color: 'yellow', fontSize: '20px', background: 'black' }; thColor = 'yellow'; thFontSz = '20px'; thBackground = 'black';
See More:
Attribute binding
SUMMARY
Summarizing, we have:
attr.
<!-- expression calculates colspan=2 --> <tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
class.
style.
@Component({ selector: 'app-nav-bar', template: ` <nav [style]='navStyle'> <a [style.text-decoration]="activeLinkStyle">Home Page</a> <a [style.text-decoration]="linkStyle">Login</a> </nav>` }) export class NavBarComponent { navStyle = 'font-size: 1.2rem; color: cornflowerblue;'; linkStyle = 'underline'; activeLinkStyle = 'overline'; /* . . . */ }
EVENT BINDING
Above, it was already shown an event binding using (input)=”0″.
Let’s see others.
A simple event binding works like this, according to Angular documentation:
Example
app.component.html:
Parent-Child Relationship – Sending data from Parent to Child
This tutorial has a very fast approach, useful for revisions and fast learning, but sometimes, when the concept is a little more tricky, may be helpful to extend the approach.
If desired detailed information, please take a look at @Input/@Output documentation.
Also, you may check other sources referenced below under Credits topic, at the page’s bottom.
To go ahead, it is necessary to create app’s child, run on prompt, under project’s root folder, the following command:
ng g c app-child
Result:
Example
1. Edit app.component.ts and declare childName just after class declaration. Example:
export class AppComponent { childName = 'app-child';
error TS2339: Property ‘childName’ does not exist on type ‘AppComponent’.
So, when having this kind of compilation issue, try to move the not recognized property to a closer position to the class declaration.
2. Edit app-child.component.ts and add:
Edit app-child.component.html and replace the default code with:
3. Edit app.component.html and set:
<h4>Event Binding @Input</h4> <app-app-child [myName]="childName"></app-app-child>
Go to the app-child.component.ts file and check its selector name:
@Component({ selector: 'app-app-child',
4. Result:
Parent-Child Relationship using EventEmitter
This example comes from Angular doc where you may find additional information.
Here, the example is summarized to attend the purpose of this post (revision/fast learning).
Some small changes were done to adjust to the current sequence ot the tutorial.
1. Add to app-child.component.ts:
@Output() newItemEvent = new EventEmitter<string>();
addNewItem(value: string): void { this.newItemEvent.emit(value); }
Obs.:
a. It is used the import already created in the previous topic.
b. EventEmitter<string>
—the @
Output()
‘s type
2. Add to app-child.component.html:
<label>Add an item: <input #newItem></label> <button (click)="addNewItem(newItem.value)">Add to parent's list</button>
3. Add to app.component.ts:
items = ['item1', 'item2', 'item3', 'item4']; // set this with the other properties, near to class definition. // append the method to the end of the file addItem(newItem: string): void { this.items.push(newItem); }
4. Append to app.component.html:
The highlighted code is the prior code used in the previous topic.
Now, as part of our exercise, we are going to “merge” both examples into just one, since we are using the same output element (app-app-child).
Follow by the images.
BEFORE
AFTER
<h4>Event Binding - Child</h4> <app-app-child [myName]="childName" (newItemEvent)="addItem($event)"></app-app-child> <h4>Event Binding - Parent</h4> <ul> <li *ngFor="let item of items">{{item}}</li> </ul> <br /><br />
RESULT
The “olá” (portuguese word for hello) is pushed into the items array when the button is pressed.
You, see! Here you also learn portuguese!
Ok! Let’s go ahead because there is still road to run!!
Two-way Binding: @Input()
and @
Output()
together
Angular documentation – Two-way binding
How two-way data binding works
In this kind of binding the data is passed to the child and vice-versa.
To make it work, there is a rule: the event name must follow a syntax that is the concatenation of the “@Input” attribute name plus the “Change” suffix.
Example:
@Input() sportCode: number; @Output() sportCodeChange = new EventEmitter<number>(); sportItens = ['ball', 'football boots', 'shirt', 'shorts', 'sockets']; @Input() sportItem: string; @Output() sportItemChange = new EventEmitter<string>();
Two-way Binding – property and property
PREVIOUS CODE TO BE REFACTORED (app.component.html BEFORE)
AFTER REFACTORING (app.component.html AFTER)
<app-app-child [(sportItem)]="currentSportItem" (sportItemChange)="currentSportItem=$event" [(sportCode)]="currentSportCode" (sportCodeChange)="currentSportCode=$event" [myName]="childName" (newItemEvent)="addItem($event)"> </app-app-child>
PARENT IMPLEMENTATION (app.component.ts)
currentSportCode = 0;
CHILD IMPLEMENTATION (app-child.component.ts)
sportItens = ['ball', 'football boots', 'shirt', 'shorts', 'sockets']; @Input() sportCode: number; @Output() sportCodeChange = new EventEmitter<number>(); @Input() sportItem: string; @Output() sportItemChange = new EventEmitter<string>(); // ... inc(): void { this.sportCode += 1; this.nextCode(this.sportCode); this.nextItem(this.sportCode); } nextCode(num: number): void { this.sportCode = (this.sportCode % 5); this.sportCodeChange.emit(this.sportCode); } nextItem(idx: number): void { this.sportItem = this.sportItens[idx]; this.sportItemChange.emit(this.sportItem); }
Comparing parent vs. child implementation, you may notice that the child has all the code to make it happen, and the parent just the two properties that sends and receives data.
AFTER PRESSING BUTTON (+)
Two-way Binding – property and method
The image below belongs to the Angular documentation and it is shown at the bottom of this page, but without the respective implementation.
Let’s implement this code as an exercise but adjusting to our pre-existante implementation.
After all, this is our developer’s daily life-style routine, combining and merging code everywhere, every day …
The image above tells us the following:
1. The child select in our implementation will be replaced by the selector created by the new component’s selector (app-app-item).
<app-app-item [item]=”currentItem” (deleteRequest)=”crossOffItem($event)” ></app-app-item>
2. In the child’s source, there is one “@Input” property denoted by “item” and the respective “@Output” event denoted by “deleteRequest”.
3. The parent’s source has one property and one method, respectively denoted by “currentItem” and “crossOffItem(event)”.
Creating the component and Implementing code
ng g c app-item
Opening the app-item.component.ts file created by the command above, we may check the child selector that shall be used in parent’s html file:
@Component({ selector: ‘app-app-item’, templateUrl: ‘./app-item.component.html’, styleUrls: [‘./app-item.component.css’] })
Code Implementation
app.component.ts
crossOffItem(event: EventEmitter<void>): void { this.items.shift(); }
app-item.component.ts
export class AppItemComponent implements OnInit { @Input() item: string; @Output() deleteRequest = new EventEmitter<void>(); constructor() { } ngOnInit(): void { } del(): void { this.deleteRequest.emit(); } }
app-item.component.html
<h4>Event Binding @Output - Item</h4> <label>Delete item: {{sportCode}}</label><br /><br /> <button (click)="del()" title="delete"><img src="../../assets/img/delete_30x30.jpg" /></button><br />
app.component.html
<h4>Event Binding - Parent</h4> <ul> <li *ngFor="let item of items">{{item}}</li> </ul> <br /><br /> <app-app-item [item]="currentItem" (deleteRequest)="crossOffItem($event)" ></app-app-item>
RESULT
Initial status
After two clicks on the garbage
Two-way data binding with ngModel
See Displaying and updating properties with ngModel at Angular documentation
In the app.component.ts file, set:
person = { name: 'Mary', lastname: 'Doe' };
nameToUppercase(name: string): void { this.person.name = name.toUpperCase(); }
In the app.component.html file, append:
<h4>Event Binding using ngModel</h4> <p>Current item name: {{currentItem}}</p> <p> <label for="example-ngModel">[ngModel]:</label> <input [ngModel]="person.name" (ngModelChange)="nameToUppercase($event)" id="example-ngModel"> </p>
Result
Starts as Person’s name.
Then typing in the input field, it is converted to upper case:
NOTE: error NG8002
If you get the following error:
error NG8002: Can’t bind to ‘ngModel’ since it isn’t a known property of ‘input’
see the solution at:
alsdias.blogspot.com/2021/03/javascript-error-ng8002-cant-bind-to.html
Migrating all the examples from Angular’s Built-in Directives post
In this example, since Angular documentation has many useful examples, it’s interesting to bring them in because it is useful as a code repository for later consultation.
The original project may be found here: built-in-directives.zip from Built-in Directives page.
To migrate the ngModel’s examples from built-in-directives.zip it was created two additional packages.
ng g c child-ng
ng g c item-detail
Notice that both packages don’t have the “app” prefix because their code come from external source.
For more details, the source code may be found on GitHub, “step3” tag.
CLOSING
This step continues on step-4 where bootstrap will be used to supply a better visual experience.
This source code may be found on GitHub, “step3” tag.
NEXT
Angular From Scratch Tutorial – Index
NEXT: Angular From Scratch Tutorial – Step 4: Adding Bootstrap
PREVIOUS: Angular From Scratch Tutorial – Step 2: Components
Credits
angular.io/guide/architecture
angular.io/guide/architecture-components
angular.io/tutorial
angular.io/guide/glossary#data-binding
angular.io/guide/interpolation
angular.io/guide/architecture-components
www.telerik.com/blogs/understanding-angular-property-binding-and-interpolation
angular.io/guide/event-binding
angular.io/api/core/Output
angular.io/guide/inputs-outputs
Brazilian system analyst graduated by UNESA (University Estácio de Sá – Rio de Janeiro). Geek by heart.