DEV Community

Cover image for What's new in Angular 17.3
Gergely Szerovay for This is Angular

Posted on • Originally published at angularaddicts.com

What's new in Angular 17.3

Since I published my Master Angular 17 Study guide and Master Angular 17.1 and 17.2 Study guide, the Angular team released a new minor version: 17.3.

🎯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:

  • output() API for emitting output from a component
  • outputFromObservable() helper function for transforming an observable to a component's output()
  • outputToObservable() helper function for converting a component's output to an observable
  • hostAttributeToken() class, it creates a token that can be used to inject static attributes of the host node
  • Typescript 5.4 support

📌New output() API

Official docs: output
PR: Finalizing output() and outputFromObservable() APIs

Angular 17.3 introduced the new output() API, for emitting output from a component. This API is designed to complement the input() and model() APIs, and it's type safe:

@Component({
  selector: 'app-output',
  standalone: true,
  template: `
    <button (click)="onClick.emit()">Button</button>
    <input #in type="text" (keyup)="onChange.emit(in.value)" />
  `,
})
export class OutputComponent {
  onClick = output();          // 👈 OutputEmitterRef<void>
  onChange = output<string>(); // 👈 OutputEmitterRef<string>
}

@Component({
  selector: 'app-output-wrapper',
  standalone: true,
  imports: [OutputComponent],
  template: ` <app-output (onClick)="log('onClick')" (onChange)="log('onChange', $event)" /> `,
})
export class OutputWrapperComponent {
  log(t1: string, t2: string = '') { console.log(t1, t2); }
}

// after you click on the button, then type 'test' into the input field, 
// the messages on the console are:
// onClick 
// onChange t
// onChange te
// onChange tes
// onChange test
Enter fullscreen mode Exit fullscreen mode

📌outputFromObservable() and outputToObservable helper functions

Official docs: outputFromObservable, outputToObservable
PR: Finalizing output() and outputFromObservable() APIs

In addition the new output() API, Angular 17.3 also contains the outputFromObservable() helper function for transforming an observable to a component's output():


@Component({
  selector: 'app-output2',
  standalone: true,
  template: `<button (click)="onClick$.next('click2')">Button</button>`,
})
export class Output2Component {
  onClick$ = new BehaviorSubject(''); // 👈 BehaviorSubject<string>
  onClick = outputFromObservable(this.onClick$); // 👈 OutputRef<string>
}

@Component({
  selector: 'app-output-wrapper2',
  standalone: true,
  imports: [Output2Component],
  template: `<app-output2 (onClick)="log('onClick', $event)" />`,
})
export class OutputWrapper2Component {
  log(t1: string, t2: string = '') { console.log(t1, t2); }
}

// after you click on the button, the message on the console is:
// onClick click2
Enter fullscreen mode Exit fullscreen mode

There is also a outputToObservable() helper function for converting a component's output to an observable:


@Component({
  selector: 'app-output3',
  standalone: true,
  template: `<button (click)="onClick.emit()">Button</button>`,
})
export class Output3Component {
  onClick = output(); // 👈 OutputEmitterRef<void>
}

@Component({
  selector: 'app-output-wrapper3',
  standalone: true,
  imports: [Output3Component],
  template: `<app-output3/>`, // 👈 no (onClick)="..." here!
})
export class OutputWrapper3Component implements OnInit {
  childComponent = viewChild(Output3Component);
  destroyRef = inject(DestroyRef);

  ngOnInit(): void {
    const childComponent = this.childComponent();
    if (childComponent) {
      const onClick$ = outputToObservable(childComponent.onClick) // 👈 
        .pipe(takeUntilDestroyed(this.destroyRef));
      onClick$.subscribe(() => console.log('onClick'));
    }
  }
}

// after you click on the button, the message on the console is:
// onClick
Enter fullscreen mode Exit fullscreen mode

📌HostAttributeToken() class

Official docs: HostAttributeToken
PR: feat(core): add API to inject attributes on the host node

The HostAttributeToken() class creates a token that can be used to inject static attributes of the host node. It works similarly to constructor(@Attribute('value') type: string), but uses the newer inject() API instead of the @Attribute decorator.

@Component({
  selector: 'app-hat',
  standalone: true,
  template: `<div>{{ value }}</div>
    <div>{{ value2 }}</div>`,
})
export class HatComponent {
  // 👇 required, we get a DI error if the attribute is not specified
  value = inject(new HostAttributeToken('value'));
  // 👇 optional attribute
  value2 = inject(new HostAttributeToken('value2'), 
    { optional: true }) || 'Default value';
}

@Component({
  selector: 'app-hat-wrapper',
  standalone: true,
  imports: [HatComponent],
  //    we don't specify the optional 'value2' attribute, 
  // 👇 so its value is 'Default value' 
  template: `<app-hat value="Hello" />`,
})
export class HatWrapperComponent {}
Enter fullscreen mode Exit fullscreen mode

In his article, Netanel Basal explains in more details how this new feature works.

📌Typescript 5.4 support

PR: feat(core): support TypeScript 5.4

Daniel Rosenwasser highlighted the most interesting new features of Typescript 5.4 in his announcement:

  • Preserved Narrowing in Closures Following Last Assignments
  • The NoInfer Utility Type
  • Object.groupBy and Map.groupBy
  • Support for require() calls in --moduleResolution bundler and --module preserve
  • Checked Import Attributes and Assertions
  • Quick Fix for Adding Missing Parameters
  • Auto-Import Support for Subpath Imports

👨‍💻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!

Top comments (0)