Angular’s New Era: Unveiling the Most Exciting Features Yet

  • Simple Angular app
  • Standalone angular component
  • Control flow (@if, @for, @switch)
  • Routes 
  • Lazyloading
  • Hydration SSR Story
  • Signals angular
  • Performance boost
  • Upcoming features

Agenda

Simple Angular App

@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

JS Size Comparison chart

Todo application size

JS Size Comparison chart - new

Standalone Component

@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 { }

Conditional Rendering - if

@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 { }

Control flow - For

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>();
}

Control flow - Switch

<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/> 
  }
}

Deferred view load

@defer (on viewport) {
  <comment-list/>
} @loading {
  Loading ⌛️
} @error {
  Loading failed 🙁
} @placeholder {
  <img src="comments-placeholder.png">
}

goo.gle/js-benchmarks

Routes

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),
});

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

Angular Signal🚦

  • helps to update application state in optimised way
  • implementation is based on reactive principals
  • callable function 
const count = signal(1); // WritableSignal<number>
const age = signal<number>(18); // WritableSignal<number>
const user = signal<User>({
  id: 1,
  name: 'Pankaj'
}); // WritableSignal<User>

Signal Primitives

✍️ writable

🔢 📐🔀 computed

💥 effect

✍️ writable🚦

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

🔢 📐🔀  computed🚦

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

💥 effect

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');
  }
}

Signal implementation

@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

Made with Slides.com