@Component({
selector: 'app-root',
standalone: true,
template: `
Hello from {{ name }}!
`,
})
export class App {
name = 'Angular';
}
bootstrapApplication(App);
<app-root />
Hello world application size
Hello world application size - zoneless
Todo application size
@Component({
selector: 'app-root',
standalone: true,
imports: [
Navbar,
UserProfile,
],
template: `
<app-navbar />
<user-profile />
`,
})
export class App { }
@Component({
selector: 'user-profile',
template: `
<h1>User Profile</h1>
User details here...
`,
})
export class UserProfile { }
@Component({
selector: 'app-navbar',
standalone: true,
template: `
Navbar at the top
`,
})
export class Navbar { }
<app-root />
@Component({
selector: 'user-profile',
imports: [
NgIf,
UserDetails,
NoDataFound,
],
template: `
<h1>User Profile</h1>
<div *ngIf="user; else #noDataFound">
<user-details
[user]="user">
</user-details>
</div>
<ng-template #noDataFound>
<no-data-found></no-data-found>
</ng-template>
`,
})
export class UserProfile { }
@Component({
selector: 'user-profile',
imports: [
UserDetails,
NoDataFound,
],
template: `
<h1>User Profile</h1>
@if (user) {
<user-details
[user]="user" />
} @else {
<no-data-found />
}
`,
})
export class UserProfile { }
Name: {{user.name}}
<ul>
@for(hb of user.hobbies; track hb.id) {
<li> {{ hb.name }} </li>
}
@empty {
<li>
<no-data-found />
</li>
}
</ul>
@Component({
selector: 'user-details',
imports: [
NoDataFound,
NgFor,
],
template: `
Name: {{user.name}}
<ul>
<li *ngFor="hb of user.hobbies">
{{ hb.name }}
</li>
<li *ngIf="!user.hobbies.length">
<no-data-found />
</li>
</ul>
`,
})
export class UserProfile {
user = input<User>();
}
<div [ngSwitch]="accessLevel">
<admin-dashboard *ngSwitchCase="admin"/>
<moderator-dashboard *ngSwitchCase="moderator"/>
<user-dashboard *ngSwitchDefault/>
</div>
@switch (accessLevel) {
@case ('admin') {
<admin-dashboard/>
}
@case ('moderator') {
<moderator-dashboard/>
}
@default {
<user-dashboard/>
}
}
@defer (on viewport) {
<comment-list/>
} @loading {
Loading ⌛️
} @error {
Loading failed 🙁
} @placeholder {
<img src="comments-placeholder.png">
}
goo.gle/js-benchmarks
export const routes: Routes = [
{
path: 'home',
component: Home,
},
{
path: 'user',
children: [
{
path: 'edit/:id',
component: UserEdit,
},
{
path: 'add',
component: UserEdit,
},
{
path: 'list',
component: UserList,
},
]
},
{
path: '**',
redirectTo: 'home',
},
];
// main.ts
bootstrapApplication(AppComponent, {
provideRoute(routes),
});
export const routes: Routes = [
{
path: 'home',
component: Home,
},
{
path: 'user',
loadChildren: () => import('./user/routes')
},
{
path: '**',
redirectTo: 'home',
},
];
// user/routes.ts
export default [
{
path: 'edit/:id',
loadComponent: import('./user-edit.component'),
},
{
path: 'add',
loadComponent: import('./user-add.component'),
},
{
path: 'list',
loadComponent: import('./user-list.component'),
},
];
Hydration SSR Story
Signals angular
const count = signal(1); // WritableSignal<number>
const age = signal<number>(18); // WritableSignal<number>
const user = signal<User>({
id: 1,
name: 'Pankaj'
}); // WritableSignal<User>
✍️ writable
🔢 📐🔀 computed
💥 effect
const count = signal(0); // WritableSignal<number>
const count = signal<number>(0);
// Signals are getter functions
// calling them reads their value.
console.log('The count is: ' + count());
// Set value directly
count.set(3);
// Check count value is
console.log('The count is: ' + count()); // 3
// if want to update value based on last value
count.update(value => value + 1);
// Check count value again
console.log('The count is: ' + count()); // 4
Reference: Stackblitz
const firstName = signal('Pankaj');
const lastName = signal('Parkar');
const fullName = computed(
() => `${firstName()} ${lastName()}`
);
console.log('Firstname is ', firstName()); // 'Pankaj Parkar'
function updateFirstName() {
firstName.set('Pankaj 1');
}
updateFirstName();
console.log('FullName is ', fullName()); // 'Pankaj 1 Parkar'
Reference: Stackblitz
class TestComponent {
firstName = signal('Pankaj');
lastName = signal('Parkar');
constructor() {
effect(() => `First name is ${this.firstName()}`);
effect(() => `Last name is ${this.lastName()}`);
}
updateName() {
this.firstName.set('Pankajjj');
this.lastName.set('Parkarr');
}
}
@Component({
...,
})
export class SignalComponent {
firstName = signal('Pankaj');
lastName = signal('Parkar');
fullName = computed(() =>
`${this.firstName()} ${this.lastName()}`
);
firstNameEffect = effect(() =>
console.log(`First Name is ${this.firstName()}`)
);
updateFirstName() {
this.firstName.set('Pankajj');
this.lastName.set('Pankajj');
}
}
<table>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Full Name</th>
</tr>
<tr>
<td>{{firstName()}}</td>
<td>{{lastName()}}</td>
<td>{{fullName()}}</td>
</tr>
</table>
<button (click)="updateFirstName()">
Update FirstName
</button>
Reference: Stackblitz
Reference: Stackblitz
resource API
Performance boost
Upcoming features