SCROLL TO EXPLORE •SCROLL TO EXPLORE •
Angular 19 or 18++?

Angular 19 or 18++?

Get ready to get the nitty gritty of our lovely framework

Maksym Byelous - 4 min read

Angular 19 or 18++?

Most of us are still having fun exploring the features we got with Angular 18, myself included, there is so much code I want to refactor. As a start I want to ‘signalize’ my app from bottom to the top! And the future is coming faster and faster! So today, get ready to get into the nitty gritty of our lovely framework, as we familiarise ourselves with features that will soon become a part of our daily routine thanks to Angular 19.

Standalone keyword

The ‘Standalone’ keyword will soon be forgotten, This is because from version 19 components are recognized as standalone by default. Meaning, there is no need to explicitly state that you want a standalone component. Therefore if we have a look at the following component:

@Component({
  imports: [CommonModule],
  selector: 'app-alone-component',
  template: './alone-component.html',
})
export class AloneComponent {
}

It is recognized as standalone. Alternatively you can also still make it part of a module as before, simply by setting the standalone flag to false. Like below

@Component({
  standalone: false,
  selector: 'app-modular-component',
  template: './modular-component.html',
})
export class ModularComponent {
}

This one of course we have to declare as part of the module in order to access it. For true believers there is strawberry on top of the cake - We can enforce the usage of only standalone components in our app with the ‘strictStandalone’ compiler option. After all this will make it easier to use all the perks of standalone components such as lazy loading and defer loading to name a few.

More Signals

Signals ecosystem should be updated as well. We know signals have just become a stable feature, but true is that only the beginning. Many crucial features are still in preview. With the expectation that much of it finally gets to our table well cooked and ready for prod. Signal ‘inputs’ is something I have been using and enjoy it for its simple syntax. Just to compare

export class SomeComponent {
  @Input({ required: true }) boringName!: string;

  nickname = input.required<string>();
}

Nickname is a signal variable, to be precise its type is InputSignal. Therefore, it brings to ‘input’ all the perks of signals, such as memoization. Another benefit of the signal input feature is that no change of syntax is required for the parent component. This means we could refactor components with input only, no need to touch the parent which passes the property.

<some-component
        [boringName]="person.fullName"
        [nickname]="person.superHero">
</some-component>

Signal queries would also improve our code life balance when it comes to the element references we use so often. ViewChild/viewChildren and ContentChild/ContentChildren will also be ‘signalized’ soon

export class SomeComponent {
  description = viewChild<ElementRef>('description');
  footer = contentChild(Footer);
  myBlocks = contentChildren<ElementRef>('block');
}

RxJs Interop

Let's not forget that RxJs Interop is in preview in the current version. I think it is important to get something finalised in the next major update. My hope is that at least ‘toSignal’ and ‘toObservable’ will get the final improvement needed to solidify this feature . Since starting to use signals application wide we found ourselves in components where we use observables and signals at the same time. Naturally this leads us to situations when we might want to mix or combine values. For example, add value of signal to train of few observables. Function toObservable would help us here, it is straightforward, no need to explain what it does. But I think it's important we understand that such functions actually create an environment where we could add new features like signals gradually and locally, component by component. We don’t need to refactor all components around new one full of signals. Backward compatibility.

Effect function

The Effect function got a lot of buzz around it. Probably a bit too raw when we put our hands on it for the first time. With Angular 19 there are a couple important changes coming our way as a result of evolution. Initially the effect function does not allow set signal values and computed signal is the way to go in case one signal is dependent on the value of another signal. But life is more ‘fun’ than we want it to be, and we discovered many developers want to set signals in the effect function. This is now possible using the allowSignalWrites flag.

export class TestComponent implements OnInit {
  nickname = signal('not a hero');
  fullName = signal('Max');

  constructor() {
    effect(() => {
      if (this.fullName() === 'Clark Kent') {
        this.nickname.set('Superman');
      }
    }, { allowSignalWrites: true });
  }

  ngOnInit() {
    setTimeout(() => {
      this.fullName.set('Clark Kent');
    }, 5000);
  }
}

But from now Angular will support signal values setting in effect function out of the box, no need to flag anymore. So this option goes away:

{
  allowSignalWrites: true
}

It opens doors for some less than ideal practices, but the framework team doesn't want to stay in the way of developers in this case. Responsibility goes totally to the developer on this one and I believe most of us will do the right thing like I do here

export class TestComponent implements OnInit {
  fullName = signal('Max');
  nickname = computed(() => {
    return this.fullName() === 'Clark Kent' ? 'Superman' : 'not a hero';
  });

  ngOnInit() {
    setTimeout(() => {
      this.fullName.set('Clark Kent');
    }, 5000);
  }
}

In most cases, a computed signal will save the day! And if not, the Angular team promises to provide us with a proper instrument to build our great applications, reliable, scalable and high performance. Looking forward to it!

Photo of Maksym Byelous

Maksym Byelous

Senior Software Engineer