Nathan Wailes - Blog - GitHub - LinkedIn - Patreon - Reddit - Stack Overflow - Twitter - YouTube
Angular.js
- 1 Learning resources
- 1.1 Tutorials
- 1.2 Misc StackOverflow questions
- 1.3 SCSS
- 1.4 Udemy - Max Schwarzmüller - Master Angular: The Complete Course
- 1.4.1 Summary of key ideas from the course I want to remember
- 1.4.2 Section 1: Getting Started
- 1.4.3 Section 2: The Basics
- 1.4.4 Section 4: Debugging
- 1.4.5 Section 5: Components & Databinding Deep Dive
- 1.4.6 Section 7: Directives Deep Dive
- 1.4.7 Section 9: Using Services & Dependency Injection
- 1.4.8 Section 11: Changing Pages with Routing
- 1.4.9 Section 13: Understanding Observables
- 1.4.10 Section 15: Handling Forms
- 1.4.11 Section 17: Using Pipes to Transform Output
- 1.4.12 Section 18: Making Http Requests
- 1.4.13 Section 20: Authentication & Route Protection in Angular
- 1.4.14 Section 21: Dynamic Components
- 1.4.15 Section 22: Angular Modules & Optimizing Angular Apps
- 1.4.16 Section 23: Deploying an Angular App
- 1.4.17 Section 24: Standalone Components
- 1.4.18 Section 25: Angular Signals
- 1.4.19 Section 26: Using NgRx for State Management
Learning resources
Tutorials
Misc StackOverflow questions
SCSS
Using CSS classes to style the parent div of a component
Every component has a “parent” div that doesn’t show up in the actual template (.html) file, but shows up in the rendered HTML as
<your-component-name>
. Sometimes you may want to apply CSS classes to that div, but you can't just addclass="your-class-name"
in the template file because the div doesn’t show up there.If you want the class to always be applied, add a line like this to the top of your component’s class definition:
@HostBinding('class.your-class-name')
If you want the application of the CSS class to depend on a prop passed into the component, add a line like this:
@HostBinding('class.your-class-name') useMyClassName: boolean = false;
You will then need to update the SCSS file to have the selector as
:host(.your-class-name)
if you want SCSS rules nested within that class to work. Again, if you don’t add:host()
, any nested rules just won’t show up.
Udemy - Max Schwarzmüller - Master Angular: The Complete Course
https://www.udemy.com/course/the-complete-guide-to-angular-2/
Max is a great teacher. I basically learned Vue.js from him. Yes, at times the official docs will provide just-as-good of an explanation of something, but even just an incrementally-better explanation that what you’d find in the docs (like, with clear examples) is worth a lot.
I’m omitting some course sections from my notes that were just course projects or less-important information.
Summary of key ideas from the course I want to remember
Section 2: The Basics
Angular uses modules to bundle components into packages.
Summary of databinding syntax:
String interpolation is the same as Vue.
Property binding:
[property]="expression"
(Vue syntax is:property="expression"
)Event binding:
(event)="functionToCall()"
(Vue syntax is@event="functionToCall"
)Two-way binding:
[(ngModel)]="variable"
(Vue syntax isv-model="variable"
)
Section 1: Getting Started
This was very basic stuff that I didn’t care to take notes on, like explaining what TypeScript is, how to start a project, how to install Angular, advice for how to get the most out of the course, etc.
Section 2: The Basics
How an Angular app gets loaded and started
The
index.html
file in your repo is the file served by the server.Look at the
app.component.ts
and look at theselector
attribute (app-root
). That's how the server knows to replace theapp-root
in theindex.html
with our app.component.html code.When
ng serve
rebuilds the project, the injected JavaScript imports will be updated.The code in
main.ts
file is the first code that gets executed. ThebootstrapModule
method is what gets the app started. You can see it loads theAppModule
which is inapp.module.ts
. In that file you can see all the components that should be known to the app being registered.
Components are important!
The core idea of Angular is that projects are made up of components, each of which can have its own HTML code / logic / styling.
We start projects with a "root" component (
AppComponent
), in which we'll nest other components.
Creating a new component
Generally, in an Angular CLI project, all your app-related content will go into an
app
folder.Each component should generally have its own folder, named after the component.
A component is just a TypeScript class.
The naming convention for naming a component class is to have the name of the component and then
Component
, so, like,ServerComponent
.To get the class working as an Angular class we need to add the
@Component()
decorator.We also need to configure the class, giving Angular information it needs to use the class properly. We do this by passing an object to the
@Component()
decorator.We need to specify the HTML selector for the component and the path to the template code.
Understanding the role of AppModule
and component declaration
Angular uses modules to bundle components into packages.
Just as with components, we create a module by adding a decorator (
@NgModule
) with an object configuration to a plain JavaScript class.The
bootstrap
config option tells Angular which component to use as the entry point.The
declarations
config option tells Angular to include the specified components in the module.The
imports
config option allows you to include / use other modules in your module. So it's like therequirements.txt
in Python.
Using Custom Components
In this video he just shows himself adding his custom component’s HTML tag to the root app component’s template file.
Creating Components with the CLI & Nesting Components
You can create new components with the CLI. Make sure you have the
ng serve
command running in one terminal window when you run this command in another window.The command is
ng generate component <component-name>
orng g c <component-name>
for short.The ‘nesting’ referred to in the lesson title doesn’t refer to the file structure of the code, as the two components he uses to demonstrate ‘nesting’ are at the same level as each other. He just creates a
servers
component which has as its template two instances of theserver
component.
Working with Component Templates
You can define your component template within the
.ts
file using the sametemplate
attribute you normally pass the path to the template file.To have newlines in the template in the
.ts
file, wrap the template code in backticks.
Working with Component Styles
He shows a simple example of adding custom CSS to the component’s CSS file (changing the color of an
h3
tag).You can pass multiple CSS files to the
styles
component attribute.You can add your custom CSS directly in the
.ts
file just like with the template code, which is nice when you have very little custom CSS for the component.
Fully Understanding the Component Selector
You can have your selector be an HTML attribute by enclosing the selector name in square brackets:
Example
selector
value:'[app-servers]'
Example usage in a template:
<div app-servers></div>
You can also have the selector be a CSS class:
Example
selector
value:'.app-servers'
Example usage in a template:
<div class="app-servers"></div>
What is Databinding?
Databinding is communication between your TypeScript code and the template.
There are different forms that this communication can take:
If we want to output data from our TS code to the template, we can use:
String interpolation (
{{ data }}
), or…Property binding (
[property]="data"
)
If we want our TS code to react to user events, we can use:
Event Binding (
(event)="expression"
)
We can combine both with “two-way binding” (
[(ngModel)]="data"
)
String Interpolation
Use the syntax
{{ expression }}
to do string interpolation in a template.The expression just needs to resolve to a string or something that can be converted to a string (like a number).
When defining custom methods in a component class, you just define them at the top level of the class. You don’t nest them in a “methods” object or something.
Property Binding
He spends a fair amount of time showing himself creating a
setTimeOut
function in theconstructor
to update a variable, which isn’t relevant to the topic at hand.To bind the value of a property to an expression, wrap the property in square brackets like this:
<button [disabled]="!allowNewServer"></button>
So it's like
v-bind:
or:
in Vue:<button :disabled="!allowNewServer"></button>
Property Binding vs String Interpolation
Use string interpolation when you want to display some string in the template, use property binding when you want to control the value of a property using an expression.
Remember not to use curly braces where you’re supposed to put an expression.
Event Binding
He likes to name his component functions that called by some event starting with “on”, like
onEventCreated
Angular uses parentheses to indicate events:
<button (click)="onEventCreated()"></button>
So it’s the equivalent of
@
in Vue:<button @click="onEventCreated">
But you need to include the parentheses when calling a function in Angular.
Bindable Properties and Events
To see what properties and events an HTML element offers, use
console.log()
on the element.The MDN docs also have lists of the properties and events available for HTML elements; search Google and you should find the relevant docs.
Passing and Using Data with Event Binding
We can capture event data by passing the
$event
object to the function we call.The
target
attribute of the event object is the HTML element.The
value
attribute of an input event object is the user-entered value of the input.
Two-Way Databinding
He just explains what two-way binding is. It’s the same as v-model in Vue.
Understanding Directives
Directives are instructions in the DOM.
Component tags in our templates are an example of such instructions.
There are directives with a template (like components) and directives without templates.
Typically you’ll create directives that are placed in your templates like HTML attributes.
He gives an example of an
appTurnGreen
directive.Example code:
Using ngIf to Output Data Conditionally
So far we haven’t used any directives aside from components (which are considered directives).
The syntax is
*ngIf ="expression"
The
*
identifies this directive as a “structural” directive, meaning it can change the structure of the DOM.
Enhancing ngIf with an Else Condition
The syntax is actually pretty different from Vue:
The
#
identifies a local reference.
Styling Elements Dynamically with ngStyle
The other type of directives are “attribute directives”, which don’t have a leading “*”.
To use the
ngStyle
directive we need to surround it in square brackets.His example:
<p [ngStyle]="{backgroundColor: getColor()}">
NW note: The equivalent in Vue is
:style=
He spends a minute making sure that we understand that the square brackets (property binding) and the directive name are two different features of Angular.
Applying CSS Classes Dynamically with ngClass
ngClass
allows you to dynamically set CSS classes.This works like in Vue.
It takes an object where the keys are the CSS classes and the values are expressions to determine whether to enable that CSS class.
Outputting Lists with ngFor
The syntax is
*ngFor="let obj of objs"
Getting the Index when using ngFor
The syntax is
*ngIf="let obj of objs; let i = index"
Section 4: Debugging
Understanding Angular Error Messages
Open the Chrome devtools and check the console.
He examines the following example error that shows up in the console:
The first important part is that it is telling us the error is in the
./AppComponent
component.The second important clue is that it’s in the “inline template”, with line number 4 and column number 6.
Unfortunately the “line 4, column 6” part is not helpful to us, because that’s the line in the compiled version of the code rather than the source code.
The last piece of important information is the message “Cannot read property ‘push’ of undefined”.
This is how we’ll actually find the error: there’s only one place where we call “push” in our AppComponent code.
Another way to find the error would be to notice it is raised when we click the button, and therefore is likely to be somewhere in the function that handles that button click.
The issue in this particular case is that we’re defining the
servers
variable but not setting its initial value to an empty array.So the takeaway is: try to use the error message in the console to identify which file/component is the source of the error, and the particular error it’s encountering in that file/component, and that should hopefully give you enough information to track down what’s happening.
Debugging Code in the Browser Using Sourcemaps
Sometimes you’ll have problems that don’t produce an error message, like the last item in a list not being deleted when you click on it.
In the Chrome Devtools, go to the Sources tab.
The
main.bundle.js
is the actual file being used by the browser, but it’s not our original source. If we try to set a breakpoint in themain.bundle.js
file Chrome will jump us to the relevant source file.These file support “source maps” allow Chrome to map the bundled JavaScript code that’s actually getting executed to the original source code.
While the code is halted by a breakpoint, you can hover over variables in the code to see their values.
To directly browser your source files, go to the
webpack://
section in the left sidebar of the “Sources” tab, then expand the./src/app/
directory.
Section 5: Components & Databinding Deep Dive
Module Introduction
We’re going to dive deeper into components and databinding.
We’re going to improve an example project using components and databinding.
Splitting Apps into Components
Our example app has two text fields that allow us to define a “Server Name” and a “Server Content”, and two buttons that allow us to “Add Server” or “Add Server Blueprint”, with the only difference between a server and a server blueprint being how the server content text field is displayed (with all servers and blueprints also being shown on this single page).
Right now all the code is in our
AppComponent
class.We could create a new component for where we create new servers, and a component for displaying a created server/blueprint.
He uses the CLI to create the two new components:
ng g c component-name --spec false
--spec false
makes it so that no testing files will be created for this component.
He cuts the relevant code from the
AppComponent
template file and component file and pastes it into the new components.He wants to keep the
servers
variable in theAppComponent
because we need to access it from the two child components (the “input” component and the “display” component).Breaking up the code this way has broken our app because we don’t have a way to pass data between our components. We’re going to fix that next.
Property & Event Binding Overview
Binding to Custom Properties
Assigning an Alias to Custom Properties
Binding to Custom Events
Assigning an Alias to Custom Events
Custom Property and Event Binding Summary
Understanding View Encapsulation
More on View Encapsulation
Using Local References in Templates
@ViewChild() in Angular 8+
Getting Access to the Template & DOM with @ViewChild
Projecting Content into Components with ng-content
Understanding the Component Lifecycle
Seeing Lifecycle Hooks in Action
Lifecycle Hooks and Template Access
@ContentChild() in Angular 8+
Getting Access to ng-content with @ContentChild
Wrap Up
Section 7: Directives Deep Dive
Section 9: Using Services & Dependency Injection
Section 11: Changing Pages with Routing
Section 13: Understanding Observables
Section 15: Handling Forms
Section 17: Using Pipes to Transform Output
Section 18: Making Http Requests
Section 20: Authentication & Route Protection in Angular
Section 21: Dynamic Components
Section 22: Angular Modules & Optimizing Angular Apps
Section 23: Deploying an Angular App
Section 24: Standalone Components
Section 25: Angular Signals
Section 26: Using NgRx for State Management