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.
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:
- 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📌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 click2There is also a new 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📌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 {}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 - NoInferUtility Type
- Object.groupByand- Map.groupBy
- Support for - require()calls in- --moduleResolution bundlerand- --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!


