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

15

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!

Image of Timescale

๐Ÿš€ pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applicationsโ€”without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post โ†’

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up