Migrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applications, planning framework migrations, or modernizing legacy Angular code.
/plugin marketplace add wshobson/agents/plugin install framework-migration@claude-code-workflowsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Master AngularJS to Angular migration, including hybrid apps, component conversion, dependency injection changes, and routing migration.
// main.ts - Bootstrap hybrid app
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app/app.module';
platformBrowserDynamic()
.bootstrapModule(AppModule)
.then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule);
// Bootstrap AngularJS
upgrade.bootstrap(document.body, ['myAngularJSApp'], { strictDi: true });
});
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';
@NgModule({
imports: [
BrowserModule,
UpgradeModule
]
})
export class AppModule {
constructor(private upgrade: UpgradeModule) {}
ngDoBootstrap() {
// Bootstrapped manually in main.ts
}
}
// Before: AngularJS controller
angular.module('myApp').controller('UserController', function($scope, UserService) {
$scope.user = {};
$scope.loadUser = function(id) {
UserService.getUser(id).then(function(user) {
$scope.user = user;
});
};
$scope.saveUser = function() {
UserService.saveUser($scope.user);
};
});
// After: Angular component
import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';
@Component({
selector: 'app-user',
template: `
<div>
<h2>{{ user.name }}</h2>
<button (click)="saveUser()">Save</button>
</div>
`
})
export class UserComponent implements OnInit {
user: any = {};
constructor(private userService: UserService) {}
ngOnInit() {
this.loadUser(1);
}
loadUser(id: number) {
this.userService.getUser(id).subscribe(user => {
this.user = user;
});
}
saveUser() {
this.userService.saveUser(this.user);
}
}
// Before: AngularJS directive
angular.module('myApp').directive('userCard', function() {
return {
restrict: 'E',
scope: {
user: '=',
onDelete: '&'
},
template: `
<div class="card">
<h3>{{ user.name }}</h3>
<button ng-click="onDelete()">Delete</button>
</div>
`
};
});
// After: Angular component
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-user-card',
template: `
<div class="card">
<h3>{{ user.name }}</h3>
<button (click)="delete.emit()">Delete</button>
</div>
`
})
export class UserCardComponent {
@Input() user: any;
@Output() delete = new EventEmitter<void>();
}
// Usage: <app-user-card [user]="user" (delete)="handleDelete()"></app-user-card>
// Before: AngularJS service
angular.module('myApp').factory('UserService', function($http) {
return {
getUser: function(id) {
return $http.get('/api/users/' + id);
},
saveUser: function(user) {
return $http.post('/api/users', user);
}
};
});
// After: Angular service
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UserService {
constructor(private http: HttpClient) {}
getUser(id: number): Observable<any> {
return this.http.get(`/api/users/${id}`);
}
saveUser(user: any): Observable<any> {
return this.http.post('/api/users', user);
}
}
// Angular service
import { Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class NewService {
getData() {
return 'data from Angular';
}
}
// Make available to AngularJS
import { downgradeInjectable } from '@angular/upgrade/static';
angular.module('myApp')
.factory('newService', downgradeInjectable(NewService));
// Use in AngularJS
angular.module('myApp').controller('OldController', function(newService) {
console.log(newService.getData());
});
// AngularJS service
angular.module('myApp').factory('oldService', function() {
return {
getData: function() {
return 'data from AngularJS';
}
};
});
// Make available to Angular
import { InjectionToken } from '@angular/core';
export const OLD_SERVICE = new InjectionToken<any>('oldService');
@NgModule({
providers: [
{
provide: OLD_SERVICE,
useFactory: (i: any) => i.get('oldService'),
deps: ['$injector']
}
]
})
// Use in Angular
@Component({...})
export class NewComponent {
constructor(@Inject(OLD_SERVICE) private oldService: any) {
console.log(this.oldService.getData());
}
}
// Before: AngularJS routing
angular.module('myApp').config(function($routeProvider) {
$routeProvider
.when('/users', {
template: '<user-list></user-list>'
})
.when('/users/:id', {
template: '<user-detail></user-detail>'
});
});
// After: Angular routing
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{ path: 'users', component: UserListComponent },
{ path: 'users/:id', component: UserDetailComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
<!-- Before: AngularJS -->
<form name="userForm" ng-submit="saveUser()">
<input type="text" ng-model="user.name" required>
<input type="email" ng-model="user.email" required>
<button ng-disabled="userForm.$invalid">Save</button>
</form>
// After: Angular (Template-driven)
@Component({
template: `
<form #userForm="ngForm" (ngSubmit)="saveUser()">
<input type="text" [(ngModel)]="user.name" name="name" required>
<input type="email" [(ngModel)]="user.email" name="email" required>
<button [disabled]="userForm.invalid">Save</button>
</form>
`
})
// Or Reactive Forms (preferred)
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
template: `
<form [formGroup]="userForm" (ngSubmit)="saveUser()">
<input formControlName="name">
<input formControlName="email">
<button [disabled]="userForm.invalid">Save</button>
</form>
`
})
export class UserFormComponent {
userForm: FormGroup;
constructor(private fb: FormBuilder) {
this.userForm = this.fb.group({
name: ['', Validators.required],
email: ['', [Validators.required, Validators.email]]
});
}
saveUser() {
console.log(this.userForm.value);
}
}
Phase 1: Setup (1-2 weeks)
- Install Angular CLI
- Set up hybrid app
- Configure build tools
- Set up testing
Phase 2: Infrastructure (2-4 weeks)
- Migrate services
- Migrate utilities
- Set up routing
- Migrate shared components
Phase 3: Feature Migration (varies)
- Migrate feature by feature
- Test thoroughly
- Deploy incrementally
Phase 4: Cleanup (1-2 weeks)
- Remove AngularJS code
- Remove ngUpgrade
- Optimize bundle
- Final testing
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.