Master Angular 17.1 and 17.2

A study guide that helps you learn what’s new since the 16.0 version of Angular

Gergely Szerovay
ITNEXT

--

Cover image

Since I published my Master Angular 17 Study guide, the Angular team released two minor versions: Angular 17.1 and 17.2.

🎯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 placeholders
  • ngOptimizedImage: Netlify image loader support
  • Angular CLI: clearScreen option support
  • Angular 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!

--

--

Writer for

📝 Editor at AngularAddicts.com, 💻 IT engineer, full stack developer, 👨🏼‍💻 mentor and online teacher with over two decades of experience