Mark Thompson and Devin Chasanoff demonstrated agentic Angular apps, where LLMs process user input and trigger UI changes or function calls—marking a deeper integration between Angular and AI. Meanwhile, the Angular team confirmed that Signal Forms won’t make it into Angular 20.
Agentic Angular Apps
Mark Thompson and Devin Chasanoff did two live streams focused entirely on live coding.
They demonstrated how to integrate LLMs into an Angular application to build what’s called an agentic Angular app.
Agentic apps are applications that still take user input through the UI — as usual — but then use that input to prompt an LLM directly. The response from the LLM is then used to trigger changes in the UI or even call application functions if the model deems it necessary. This leads to a much deeper level of integration between Angular and large language models.
The two livestreams covered different use cases: the first showed a story generator, where users could describe an idea and Angular used the LLM’s output to generate and display visual story cards.
In the second, they built a shopping app where the LLM could automatically filter products and add items to the cart based on the user’s intent.
Q&A Session
According to last week’s Q&A session with Mark Thompson and Jeremy Elbourn from the Angular team, the feature freeze for Angular 20 has happened. Unfortunately, Signal Forms didn’t make it.
So, when your form data source is a Signal, you’ll still need to stick with the good old effect()
function to feed the values into the FormGroup
.
The session itself was quite intensive. Usually, they do some live coding, but this time it was 90 minutes of straight Q&A. Here are the key takeaways:
👉 Experimental and developer preview features could still be removed. While this is rare in practice, there’s always a slight risk.
(Timestamp: 43:35)
👉 Jeremy explained why Angular Material offers fewer components compared to other UI libraries.
Because Google uses a monorepo for all its projects, Angular Material and the apps that use it share the same source code. This makes every change very sensitive—and costly. The more components, the higher the maintenance overhead.
To help with this, the Angular team aims to make it as easy as possible to build your own component library using the Angular CDK.
(Timestamp: 55:30)
👉 Mark also hinted at a new documentation section with long-term implications. Curious to see what that turns out to be.
Vitest as experimental feature
In other news: It looks like Vitest is getting closer to official support in Angular. A PR for experimental integration just landed—and it’s already been merged.
feat(@angular/build): add experimental vitest unit-testing support
#30130
When using the application build system via the @angular/build
package (default for new projects starting in v20), a new experimental unit-test builder is available that initially uses vitest. This experimental system is intended to provide support for investigation of future unit testing efforts within the Angular CLI. As this is experimental, no SemVer guarantees are provided, the API and behavior may change, and there may be unexpected behavior. Available test runners may be added or removed as well.
The setup is somewhat different than the previous unit-testing builders. It uses a similar mechanism to that of the dev-server
and requires a buildTarget
option. This allows the code building aspects of the unit-testing process to leverage pre-existing option values that are already defined for development. If differing option values are required for testing, an additional build target configuration specifically for testing can be used.
The current vitest support has multiple caveats including but not limited to:
- No watch support
-
jsdom
based testing only (jsdom
must be installed in the project) - Custom vitest configuration is not supported
An example configuration that would replace the test
target for a project is as follows:
"test": {
"builder": "@angular/build:unit-test",
"options": {
"tsConfig": "tsconfig.spec.json",
"buildTarget": "::development",
"runner": "vitest"
}
}
Example of modified new app spec file
import { TestBed } from '@angular/core/testing';
import { App } from './app';
import { describe, test, beforeEach, afterEach, expect } from 'vitest';
describe('App', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [App],
}).compileComponents();
});
afterEach(() => TestBed.resetTestingModule());
test('should create the app', () => {
const fixture = TestBed.createComponent(App);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
test(`should have the 'vitest-example' title`, () => {
const fixture = TestBed.createComponent(App);
const app = fixture.componentInstance;
expect(app.title).toEqual('vitest-example');
});
test('should render title', () => {
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, vitest-example');
});
});
Detecting Memory Leaks
Dmytro Mezhenskyi from Decoded Frontend published a video on memory leaks. Using DevTools, he showed how something as simple as an unsubscribed subscription can still hold on to a component instance — something that can easily happen without noticing.