Master Angular 17.1 and 17.2
A study guide that helps you learn what’s new since the 17.0 version of Angular
Since I published my Master Angular 17 Study guide, the Angular team released two minor versions: Angular 17.1 and 17.2.
This article is also available on dev.to with better source code syntax highlighting.
🎯Changes and new features
In this article, I list out the most important changes and new features, also share resources that will teach you how these new Angular features work:
Model signal inputs
View queries and component queries as signals
ngOptimizedImage
: Automatic placeholdersngOptimizedImage
: Netlify image loader supportAngular CLI:
clearScreen
option supportAngular CLI:
define
option for declaring global identifiers
This article is also available on dev.to with better source code syntax highlighting.
📌Model signal inputs
PR: Initial implementation of model inputs
Angular 17.2 introduced model inputs. They based on writable signals and defines a input/output pair that can be used in two-way bindings. In the example below, the signals in the two components always have the same value, and you can increase this value by pressing on of the buttons:
@Component({
selector: 'app-counter',
standalone: true,
template: `<button (click)="increase()">Counter's button: {{ value() }}</button>`,
})
export class CounterComponent {
value = model.required<number>();
increase() {
this.value.update((x) => x + 1);
}
}
@Component({
selector: 'app-wrapper',
standalone: true,
imports: [CounterComponent],
template: `<app-counter [(value)]="count" />
<button (click)="increase()">Wrapper's button: {{ count() }}</button>`
})
export class WrapperComponent {
count = signal(0);
increase() {
this.count.update((x) => x + 1);
}
}
We can also bind an input element's value to a writable signal by two-way data binding, using the 'banana in the box' syntax [(ngModel)]
:
@Component({
selector: 'app-root',
standalone: true,
imports: [
FormsModule,
],
template: `
<textarea
[(ngModel)]="promptValue"
></textarea>`
})
export class AppComponent {
promptValue = signal('');
}
📌View queries and component queries as signals
PR: feat(core): expose queries as signals
With this improvement, we can query elements from the component's template as signals: there are new viewChild()
, viewChildren()
, contentChild()
and contentChildren()
functions that return Signals. These are signal based versions of the @viewChild
, @viewChildren
, @contentChild
and @contentChildren
decorators:
@Component({
selector: 'app-vc-query-as-signal',
standalone: true,
template: `
<button (click)="show()">Show</button>
@if(visible()) {
<div #id1>Hi!</div>
}`,
})
class VcQueryAsSignalComponent {
visible = signal(false);
divEl = viewChild<ElementRef<HTMLDivElement>>('id1'); // 👈
effectRef = effect(() => {
console.log(this.divEl());
});
show() {
this.visible.set(true);
}
}
// First message on the console: undefined
// The user clicks on the button
// Second message on the console: _ElementRef {nativeElement: div}
📌ngOptimizedImage: Automatic placeholders, Netlify image loader support
Official docs: Automatic placeholders
PR: feat(common): add Netlify image loader
PR: feat(common): add placeholder to NgOptimizedImage
NgOptimizedImage can automatically display a low-res placeholder when using an image CDN.
The Angular team has also added the provideNetlifyLoader
preconfigured loader to support the Netlify image CDN.
@Component({
selector: 'app-image',
standalone: true,
imports: [NgOptimizedImage],
template: `
<p>Responsive image:</p>
<!-- 30 x 30 url encoded image as a placeholder 👇 -->
<img ngSrc="assets/lamp.jpeg" style="max-width: 1024px" [placeholder]="data:@file/jpeg;base64,..." />
`,
})
export class ImageComponent {
}
// app.config.ts
export const appConfig: ApplicationConfig = {
// provider for the Netlify image CDN 👇
providers: [provideNetlifyLoader('https://yoursite.netlify.app/')],
};
📌Angular CLI: clearScreen option support
PR: a957ede build: update angular
Angular can clear the screen before each re-build. You can enable this feature in angular.json
, by setting the clearScreen
builder option to true
(it's false
by default):
// angular.json
{
"projects": {
"ng172": {
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
// 👇 clear the screen before each re-build
"clearScreen": true,
// ...
📌Angular CLI: 'define' option for declaring global identifiers
PR: feat(@angular-devkit/build-angular): add define build option to application builder
The application
builder supports the define
option for declaring global identifiers. As these identifiers declared in angular.json
, not in a .ts
support, we can declare it for typescript using a declare const
statement in src/types.d.ts
. We can use these identifiers as an alternate to the environment files in the future.
@Component({
template: `
Text: {{ CONSTANT_IN_ANGULAR_JSON.text }},
Number:{{ CONSTANT_IN_ANGULAR_JSON.number }}`,
})
export class GlobalIdentifierComponent {
CONSTANT_IN_ANGULAR_JSON = CONSTANT_IN_ANGULAR_JSON;
}
// angular.json
{
"projects": {
"ng172": {
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"define": {
// the value must have a valid JSON syntax 👇
"CONSTANT_IN_ANGULAR_JSON": "{ 'text': 'This constant is defined in angular.json', 'number': 1 }"
},
// ...
// src/types.d.ts
declare const CONSTANT_IN_ANGULAR_JSON: { text: string; number: number };
👨💻About the author
My name is Gergely Szerovay, I work as a frontend development chapter lead. Teaching (and learning) Angular is one of my passions. I consume content related to Angular on a daily basis — articles, podcasts, conference talks, you name it.
I created the Angular Addict Newsletter so that I can send you the best resources I come across each month. Whether you are a seasoned Angular Addict or a beginner, I got you covered.
Next to the newsletter, I also have a publication called Angular Addicts. It is a collection of the resources I find most informative and interesting. Let me know if you would like to be included as a writer.
Let’s learn Angular together! Subscribe here 🔥
Follow me on Substack, Medium, Dev.to, Twitter or LinkedIn to learn more about Angular!