[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CRSE7C5W74ADB7X3CWHZTF":3,"skill-same:01M6CRSE7C5W74ADB7X3CWHZTF":58},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":29,"linkOnly":30,"markdownContent":31,"markdownBody":32,"frontMatter":33,"refName":36,"commitSha":37,"skillDirectory":38,"forksCount":39,"repositoryHtmlUrl":40,"repositoryHomepageUrl":40,"ownerHtmlUrl":41,"ownerBlogUrl":6,"ownerDescription":42,"updatedAt":43,"install":44,"resources":57},"01M6CRSE7C5W74ADB7X3CWHZTF","angular-migration",null,"Master AngularJS to Angular migration, including hybrid apps, component conversion, dependency injection changes, and routing migration.","Sam-06060\u002Fjarvis-assistant","Sam-06060","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F208600848?v=4","01M6CRKT7C7FXD21V6HXF293S0","Samson Frank Ganta","01M6CRKTBEKYFD8YX5Z1GT99EE",6,"Apache-2.0","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fangular-migration\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28],"angular","migration","angular migration","component","routing","injection","dependency","conversion","master","community","2026-11-10 10:12:30",false,"---\nname: angular-migration\ndescription: \"Master AngularJS to Angular migration, including hybrid apps, component conversion, dependency injection changes, and routing migration.\"\nrisk: unknown\nsource: community\ndate_added: \"2026-02-27\"\n---\n\n# Angular Migration\n\nMaster AngularJS to Angular migration, including hybrid apps, component conversion, dependency injection changes, and routing migration.\n\n## Use this skill when\n\n- Migrating AngularJS (1.x) applications to Angular (2+)\n- Running hybrid AngularJS\u002FAngular applications\n- Converting directives to components\n- Modernizing dependency injection\n- Migrating routing systems\n- Updating to latest Angular versions\n- Implementing Angular best practices\n\n## Do not use this skill when\n\n- You are not migrating from AngularJS to Angular\n- The app is already on a modern Angular version\n- You need only a small UI fix without framework changes\n\n## Instructions\n\n1. Assess the AngularJS codebase, dependencies, and migration risks.\n2. Choose a migration strategy (hybrid vs rewrite) and define milestones.\n3. Set up ngUpgrade and migrate modules, components, and routing.\n4. Validate with tests and plan a safe cutover.\n\n## Safety\n\n- Avoid big-bang cutovers without rollback and staging validation.\n- Keep hybrid compatibility testing during incremental migration.\n\n## Migration Strategies\n\n### 1. Big Bang (Complete Rewrite)\n- Rewrite entire app in Angular\n- Parallel development\n- Switch over at once\n- **Best for:** Small apps, green field projects\n\n### 2. Incremental (Hybrid Approach)\n- Run AngularJS and Angular side-by-side\n- Migrate feature by feature\n- ngUpgrade for interop\n- **Best for:** Large apps, continuous delivery\n\n### 3. Vertical Slice\n- Migrate one feature completely\n- New features in Angular, maintain old in AngularJS\n- Gradually replace\n- **Best for:** Medium apps, distinct features\n\n## Hybrid App Setup\n\n```typescript\n\u002F\u002F main.ts - Bootstrap hybrid app\nimport { platformBrowserDynamic } from '@angular\u002Fplatform-browser-dynamic';\nimport { UpgradeModule } from '@angular\u002Fupgrade\u002Fstatic';\nimport { AppModule } from '.\u002Fapp\u002Fapp.module';\n\nplatformBrowserDynamic()\n  .bootstrapModule(AppModule)\n  .then(platformRef => {\n    const upgrade = platformRef.injector.get(UpgradeModule);\n    \u002F\u002F Bootstrap AngularJS\n    upgrade.bootstrap(document.body, ['myAngularJSApp'], { strictDi: true });\n  });\n```\n\n```typescript\n\u002F\u002F app.module.ts\nimport { NgModule } from '@angular\u002Fcore';\nimport { BrowserModule } from '@angular\u002Fplatform-browser';\nimport { UpgradeModule } from '@angular\u002Fupgrade\u002Fstatic';\n\n@NgModule({\n  imports: [\n    BrowserModule,\n    UpgradeModule\n  ]\n})\nexport class AppModule {\n  constructor(private upgrade: UpgradeModule) {}\n\n  ngDoBootstrap() {\n    \u002F\u002F Bootstrapped manually in main.ts\n  }\n}\n```\n\n## Component Migration\n\n### AngularJS Controller → Angular Component\n```javascript\n\u002F\u002F Before: AngularJS controller\nangular.module('myApp').controller('UserController', function($scope, UserService) {\n  $scope.user = {};\n\n  $scope.loadUser = function(id) {\n    UserService.getUser(id).then(function(user) {\n      $scope.user = user;\n    });\n  };\n\n  $scope.saveUser = function() {\n    UserService.saveUser($scope.user);\n  };\n});\n```\n\n```typescript\n\u002F\u002F After: Angular component\nimport { Component, OnInit } from '@angular\u002Fcore';\nimport { UserService } from '.\u002Fuser.service';\n\n@Component({\n  selector: 'app-user',\n  template: `\n    \u003Cdiv>\n      \u003Ch2>{{ user.name }}\u003C\u002Fh2>\n      \u003Cbutton (click)=\"saveUser()\">Save\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  `\n})\nexport class UserComponent implements OnInit {\n  user: any = {};\n\n  constructor(private userService: UserService) {}\n\n  ngOnInit() {\n    this.loadUser(1);\n  }\n\n  loadUser(id: number) {\n    this.userService.getUser(id).subscribe(user => {\n      this.user = user;\n    });\n  }\n\n  saveUser() {\n    this.userService.saveUser(this.user);\n  }\n}\n```\n\n### AngularJS Directive → Angular Component\n```javascript\n\u002F\u002F Before: AngularJS directive\nangular.module('myApp').directive('userCard', function() {\n  return {\n    restrict: 'E',\n    scope: {\n      user: '=',\n      onDelete: '&'\n    },\n    template: `\n      \u003Cdiv class=\"card\">\n        \u003Ch3>{{ user.name }}\u003C\u002Fh3>\n        \u003Cbutton ng-click=\"onDelete()\">Delete\u003C\u002Fbutton>\n      \u003C\u002Fdiv>\n    `\n  };\n});\n```\n\n```typescript\n\u002F\u002F After: Angular component\nimport { Component, Input, Output, EventEmitter } from '@angular\u002Fcore';\n\n@Component({\n  selector: 'app-user-card',\n  template: `\n    \u003Cdiv class=\"card\">\n      \u003Ch3>{{ user.name }}\u003C\u002Fh3>\n      \u003Cbutton (click)=\"delete.emit()\">Delete\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  `\n})\nexport class UserCardComponent {\n  @Input() user: any;\n  @Output() delete = new EventEmitter\u003Cvoid>();\n}\n\n\u002F\u002F Usage: \u003Capp-user-card [user]=\"user\" (delete)=\"handleDelete()\">\u003C\u002Fapp-user-card>\n```\n\n## Service Migration\n\n```javascript\n\u002F\u002F Before: AngularJS service\nangular.module('myApp').factory('UserService', function($http) {\n  return {\n    getUser: function(id) {\n      return $http.get('\u002Fapi\u002Fusers\u002F' + id);\n    },\n    saveUser: function(user) {\n      return $http.post('\u002Fapi\u002Fusers', user);\n    }\n  };\n});\n```\n\n```typescript\n\u002F\u002F After: Angular service\nimport { Injectable } from '@angular\u002Fcore';\nimport { HttpClient } from '@angular\u002Fcommon\u002Fhttp';\nimport { Observable } from 'rxjs';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class UserService {\n  constructor(private http: HttpClient) {}\n\n  getUser(id: number): Observable\u003Cany> {\n    return this.http.get(`\u002Fapi\u002Fusers\u002F${id}`);\n  }\n\n  saveUser(user: any): Observable\u003Cany> {\n    return this.http.post('\u002Fapi\u002Fusers', user);\n  }\n}\n```\n\n## Dependency Injection Changes\n\n### Downgrading Angular → AngularJS\n```typescript\n\u002F\u002F Angular service\nimport { Injectable } from '@angular\u002Fcore';\n\n@Injectable({ providedIn: 'root' })\nexport class NewService {\n  getData() {\n    return 'data from Angular';\n  }\n}\n\n\u002F\u002F Make available to AngularJS\nimport { downgradeInjectable } from '@angular\u002Fupgrade\u002Fstatic';\n\nangular.module('myApp')\n  .factory('newService', downgradeInjectable(NewService));\n\n\u002F\u002F Use in AngularJS\nangular.module('myApp').controller('OldController', function(newService) {\n  console.log(newService.getData());\n});\n```\n\n### Upgrading AngularJS → Angular\n```typescript\n\u002F\u002F AngularJS service\nangular.module('myApp').factory('oldService', function() {\n  return {\n    getData: function() {\n      return 'data from AngularJS';\n    }\n  };\n});\n\n\u002F\u002F Make available to Angular\nimport { InjectionToken } from '@angular\u002Fcore';\n\nexport const OLD_SERVICE = new InjectionToken\u003Cany>('oldService');\n\n@NgModule({\n  providers: [\n    {\n      provide: OLD_SERVICE,\n      useFactory: (i: any) => i.get('oldService'),\n      deps: ['$injector']\n    }\n  ]\n})\n\n\u002F\u002F Use in Angular\n@Component({...})\nexport class NewComponent {\n  constructor(@Inject(OLD_SERVICE) private oldService: any) {\n    console.log(this.oldService.getData());\n  }\n}\n```\n\n## Routing Migration\n\n```javascript\n\u002F\u002F Before: AngularJS routing\nangular.module('myApp').config(function($routeProvider) {\n  $routeProvider\n    .when('\u002Fusers', {\n      template: '\u003Cuser-list>\u003C\u002Fuser-list>'\n    })\n    .when('\u002Fusers\u002F:id', {\n      template: '\u003Cuser-detail>\u003C\u002Fuser-detail>'\n    });\n});\n```\n\n```typescript\n\u002F\u002F After: Angular routing\nimport { NgModule } from '@angular\u002Fcore';\nimport { RouterModule, Routes } from '@angular\u002Frouter';\n\nconst routes: Routes = [\n  { path: 'users', component: UserListComponent },\n  { path: 'users\u002F:id', component: UserDetailComponent }\n];\n\n@NgModule({\n  imports: [RouterModule.forRoot(routes)],\n  exports: [RouterModule]\n})\nexport class AppRoutingModule {}\n```\n\n## Forms Migration\n\n```html\n\u003C!-- Before: AngularJS -->\n\u003Cform name=\"userForm\" ng-submit=\"saveUser()\">\n  \u003Cinput type=\"text\" ng-model=\"user.name\" required>\n  \u003Cinput type=\"email\" ng-model=\"user.email\" required>\n  \u003Cbutton ng-disabled=\"userForm.$invalid\">Save\u003C\u002Fbutton>\n\u003C\u002Fform>\n```\n\n```typescript\n\u002F\u002F After: Angular (Template-driven)\n@Component({\n  template: `\n    \u003Cform #userForm=\"ngForm\" (ngSubmit)=\"saveUser()\">\n      \u003Cinput type=\"text\" [(ngModel)]=\"user.name\" name=\"name\" required>\n      \u003Cinput type=\"email\" [(ngModel)]=\"user.email\" name=\"email\" required>\n      \u003Cbutton [disabled]=\"userForm.invalid\">Save\u003C\u002Fbutton>\n    \u003C\u002Fform>\n  `\n})\n\n\u002F\u002F Or Reactive Forms (preferred)\nimport { FormBuilder, FormGroup, Validators } from '@angular\u002Fforms';\n\n@Component({\n  template: `\n    \u003Cform [formGroup]=\"userForm\" (ngSubmit)=\"saveUser()\">\n      \u003Cinput formControlName=\"name\">\n      \u003Cinput formControlName=\"email\">\n      \u003Cbutton [disabled]=\"userForm.invalid\">Save\u003C\u002Fbutton>\n    \u003C\u002Fform>\n  `\n})\nexport class UserFormComponent {\n  userForm: FormGroup;\n\n  constructor(private fb: FormBuilder) {\n    this.userForm = this.fb.group({\n      name: ['', Validators.required],\n      email: ['', [Validators.required, Validators.email]]\n    });\n  }\n\n  saveUser() {\n    console.log(this.userForm.value);\n  }\n}\n```\n\n## Migration Timeline\n\n```\nPhase 1: Setup (1-2 weeks)\n- Install Angular CLI\n- Set up hybrid app\n- Configure build tools\n- Set up testing\n\nPhase 2: Infrastructure (2-4 weeks)\n- Migrate services\n- Migrate utilities\n- Set up routing\n- Migrate shared components\n\nPhase 3: Feature Migration (varies)\n- Migrate feature by feature\n- Test thoroughly\n- Deploy incrementally\n\nPhase 4: Cleanup (1-2 weeks)\n- Remove AngularJS code\n- Remove ngUpgrade\n- Optimize bundle\n- Final testing\n```\n\n## Resources\n\n- **references\u002Fhybrid-mode.md**: Hybrid app patterns\n- **references\u002Fcomponent-migration.md**: Component conversion guide\n- **references\u002Fdependency-injection.md**: DI migration strategies\n- **references\u002Frouting.md**: Routing migration\n- **assets\u002Fhybrid-bootstrap.ts**: Hybrid app template\n- **assets\u002Fmigration-timeline.md**: Project planning\n- **scripts\u002Fanalyze-angular-app.sh**: App analysis script\n\n## Best Practices\n\n1. **Start with Services**: Migrate services first (easier)\n2. **Incremental Approach**: Feature-by-feature migration\n3. **Test Continuously**: Test at every step\n4. **Use TypeScript**: Migrate to TypeScript early\n5. **Follow Style Guide**: Angular style guide from day 1\n6. **Optimize Later**: Get it working, then optimize\n7. **Document**: Keep migration notes\n\n## Common Pitfalls\n\n- Not setting up hybrid app correctly\n- Migrating UI before logic\n- Ignoring change detection differences\n- Not handling scope properly\n- Mixing patterns (AngularJS + Angular)\n- Inadequate testing\n","# Angular Migration\n\nMaster AngularJS to Angular migration, including hybrid apps, component conversion, dependency injection changes, and routing migration.\n\n## Use this skill when\n\n- Migrating AngularJS (1.x) applications to Angular (2+)\n- Running hybrid AngularJS\u002FAngular applications\n- Converting directives to components\n- Modernizing dependency injection\n- Migrating routing systems\n- Updating to latest Angular versions\n- Implementing Angular best practices\n\n## Do not use this skill when\n\n- You are not migrating from AngularJS to Angular\n- The app is already on a modern Angular version\n- You need only a small UI fix without framework changes\n\n## Instructions\n\n1. Assess the AngularJS codebase, dependencies, and migration risks.\n2. Choose a migration strategy (hybrid vs rewrite) and define milestones.\n3. Set up ngUpgrade and migrate modules, components, and routing.\n4. Validate with tests and plan a safe cutover.\n\n## Safety\n\n- Avoid big-bang cutovers without rollback and staging validation.\n- Keep hybrid compatibility testing during incremental migration.\n\n## Migration Strategies\n\n### 1. Big Bang (Complete Rewrite)\n- Rewrite entire app in Angular\n- Parallel development\n- Switch over at once\n- **Best for:** Small apps, green field projects\n\n### 2. Incremental (Hybrid Approach)\n- Run AngularJS and Angular side-by-side\n- Migrate feature by feature\n- ngUpgrade for interop\n- **Best for:** Large apps, continuous delivery\n\n### 3. Vertical Slice\n- Migrate one feature completely\n- New features in Angular, maintain old in AngularJS\n- Gradually replace\n- **Best for:** Medium apps, distinct features\n\n## Hybrid App Setup\n\n```typescript\n\u002F\u002F main.ts - Bootstrap hybrid app\nimport { platformBrowserDynamic } from '@angular\u002Fplatform-browser-dynamic';\nimport { UpgradeModule } from '@angular\u002Fupgrade\u002Fstatic';\nimport { AppModule } from '.\u002Fapp\u002Fapp.module';\n\nplatformBrowserDynamic()\n  .bootstrapModule(AppModule)\n  .then(platformRef => {\n    const upgrade = platformRef.injector.get(UpgradeModule);\n    \u002F\u002F Bootstrap AngularJS\n    upgrade.bootstrap(document.body, ['myAngularJSApp'], { strictDi: true });\n  });\n```\n\n```typescript\n\u002F\u002F app.module.ts\nimport { NgModule } from '@angular\u002Fcore';\nimport { BrowserModule } from '@angular\u002Fplatform-browser';\nimport { UpgradeModule } from '@angular\u002Fupgrade\u002Fstatic';\n\n@NgModule({\n  imports: [\n    BrowserModule,\n    UpgradeModule\n  ]\n})\nexport class AppModule {\n  constructor(private upgrade: UpgradeModule) {}\n\n  ngDoBootstrap() {\n    \u002F\u002F Bootstrapped manually in main.ts\n  }\n}\n```\n\n## Component Migration\n\n### AngularJS Controller → Angular Component\n```javascript\n\u002F\u002F Before: AngularJS controller\nangular.module('myApp').controller('UserController', function($scope, UserService) {\n  $scope.user = {};\n\n  $scope.loadUser = function(id) {\n    UserService.getUser(id).then(function(user) {\n      $scope.user = user;\n    });\n  };\n\n  $scope.saveUser = function() {\n    UserService.saveUser($scope.user);\n  };\n});\n```\n\n```typescript\n\u002F\u002F After: Angular component\nimport { Component, OnInit } from '@angular\u002Fcore';\nimport { UserService } from '.\u002Fuser.service';\n\n@Component({\n  selector: 'app-user',\n  template: `\n    \u003Cdiv>\n      \u003Ch2>{{ user.name }}\u003C\u002Fh2>\n      \u003Cbutton (click)=\"saveUser()\">Save\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  `\n})\nexport class UserComponent implements OnInit {\n  user: any = {};\n\n  constructor(private userService: UserService) {}\n\n  ngOnInit() {\n    this.loadUser(1);\n  }\n\n  loadUser(id: number) {\n    this.userService.getUser(id).subscribe(user => {\n      this.user = user;\n    });\n  }\n\n  saveUser() {\n    this.userService.saveUser(this.user);\n  }\n}\n```\n\n### AngularJS Directive → Angular Component\n```javascript\n\u002F\u002F Before: AngularJS directive\nangular.module('myApp').directive('userCard', function() {\n  return {\n    restrict: 'E',\n    scope: {\n      user: '=',\n      onDelete: '&'\n    },\n    template: `\n      \u003Cdiv class=\"card\">\n        \u003Ch3>{{ user.name }}\u003C\u002Fh3>\n        \u003Cbutton ng-click=\"onDelete()\">Delete\u003C\u002Fbutton>\n      \u003C\u002Fdiv>\n    `\n  };\n});\n```\n\n```typescript\n\u002F\u002F After: Angular component\nimport { Component, Input, Output, EventEmitter } from '@angular\u002Fcore';\n\n@Component({\n  selector: 'app-user-card',\n  template: `\n    \u003Cdiv class=\"card\">\n      \u003Ch3>{{ user.name }}\u003C\u002Fh3>\n      \u003Cbutton (click)=\"delete.emit()\">Delete\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  `\n})\nexport class UserCardComponent {\n  @Input() user: any;\n  @Output() delete = new EventEmitter\u003Cvoid>();\n}\n\n\u002F\u002F Usage: \u003Capp-user-card [user]=\"user\" (delete)=\"handleDelete()\">\u003C\u002Fapp-user-card>\n```\n\n## Service Migration\n\n```javascript\n\u002F\u002F Before: AngularJS service\nangular.module('myApp').factory('UserService', function($http) {\n  return {\n    getUser: function(id) {\n      return $http.get('\u002Fapi\u002Fusers\u002F' + id);\n    },\n    saveUser: function(user) {\n      return $http.post('\u002Fapi\u002Fusers', user);\n    }\n  };\n});\n```\n\n```typescript\n\u002F\u002F After: Angular service\nimport { Injectable } from '@angular\u002Fcore';\nimport { HttpClient } from '@angular\u002Fcommon\u002Fhttp';\nimport { Observable } from 'rxjs';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class UserService {\n  constructor(private http: HttpClient) {}\n\n  getUser(id: number): Observable\u003Cany> {\n    return this.http.get(`\u002Fapi\u002Fusers\u002F${id}`);\n  }\n\n  saveUser(user: any): Observable\u003Cany> {\n    return this.http.post('\u002Fapi\u002Fusers', user);\n  }\n}\n```\n\n## Dependency Injection Changes\n\n### Downgrading Angular → AngularJS\n```typescript\n\u002F\u002F Angular service\nimport { Injectable } from '@angular\u002Fcore';\n\n@Injectable({ providedIn: 'root' })\nexport class NewService {\n  getData() {\n    return 'data from Angular';\n  }\n}\n\n\u002F\u002F Make available to AngularJS\nimport { downgradeInjectable } from '@angular\u002Fupgrade\u002Fstatic';\n\nangular.module('myApp')\n  .factory('newService', downgradeInjectable(NewService));\n\n\u002F\u002F Use in AngularJS\nangular.module('myApp').controller('OldController', function(newService) {\n  console.log(newService.getData());\n});\n```\n\n### Upgrading AngularJS → Angular\n```typescript\n\u002F\u002F AngularJS service\nangular.module('myApp').factory('oldService', function() {\n  return {\n    getData: function() {\n      return 'data from AngularJS';\n    }\n  };\n});\n\n\u002F\u002F Make available to Angular\nimport { InjectionToken } from '@angular\u002Fcore';\n\nexport const OLD_SERVICE = new InjectionToken\u003Cany>('oldService');\n\n@NgModule({\n  providers: [\n    {\n      provide: OLD_SERVICE,\n      useFactory: (i: any) => i.get('oldService'),\n      deps: ['$injector']\n    }\n  ]\n})\n\n\u002F\u002F Use in Angular\n@Component({...})\nexport class NewComponent {\n  constructor(@Inject(OLD_SERVICE) private oldService: any) {\n    console.log(this.oldService.getData());\n  }\n}\n```\n\n## Routing Migration\n\n```javascript\n\u002F\u002F Before: AngularJS routing\nangular.module('myApp').config(function($routeProvider) {\n  $routeProvider\n    .when('\u002Fusers', {\n      template: '\u003Cuser-list>\u003C\u002Fuser-list>'\n    })\n    .when('\u002Fusers\u002F:id', {\n      template: '\u003Cuser-detail>\u003C\u002Fuser-detail>'\n    });\n});\n```\n\n```typescript\n\u002F\u002F After: Angular routing\nimport { NgModule } from '@angular\u002Fcore';\nimport { RouterModule, Routes } from '@angular\u002Frouter';\n\nconst routes: Routes = [\n  { path: 'users', component: UserListComponent },\n  { path: 'users\u002F:id', component: UserDetailComponent }\n];\n\n@NgModule({\n  imports: [RouterModule.forRoot(routes)],\n  exports: [RouterModule]\n})\nexport class AppRoutingModule {}\n```\n\n## Forms Migration\n\n```html\n\u003C!-- Before: AngularJS -->\n\u003Cform name=\"userForm\" ng-submit=\"saveUser()\">\n  \u003Cinput type=\"text\" ng-model=\"user.name\" required>\n  \u003Cinput type=\"email\" ng-model=\"user.email\" required>\n  \u003Cbutton ng-disabled=\"userForm.$invalid\">Save\u003C\u002Fbutton>\n\u003C\u002Fform>\n```\n\n```typescript\n\u002F\u002F After: Angular (Template-driven)\n@Component({\n  template: `\n    \u003Cform #userForm=\"ngForm\" (ngSubmit)=\"saveUser()\">\n      \u003Cinput type=\"text\" [(ngModel)]=\"user.name\" name=\"name\" required>\n      \u003Cinput type=\"email\" [(ngModel)]=\"user.email\" name=\"email\" required>\n      \u003Cbutton [disabled]=\"userForm.invalid\">Save\u003C\u002Fbutton>\n    \u003C\u002Fform>\n  `\n})\n\n\u002F\u002F Or Reactive Forms (preferred)\nimport { FormBuilder, FormGroup, Validators } from '@angular\u002Fforms';\n\n@Component({\n  template: `\n    \u003Cform [formGroup]=\"userForm\" (ngSubmit)=\"saveUser()\">\n      \u003Cinput formControlName=\"name\">\n      \u003Cinput formControlName=\"email\">\n      \u003Cbutton [disabled]=\"userForm.invalid\">Save\u003C\u002Fbutton>\n    \u003C\u002Fform>\n  `\n})\nexport class UserFormComponent {\n  userForm: FormGroup;\n\n  constructor(private fb: FormBuilder) {\n    this.userForm = this.fb.group({\n      name: ['', Validators.required],\n      email: ['', [Validators.required, Validators.email]]\n    });\n  }\n\n  saveUser() {\n    console.log(this.userForm.value);\n  }\n}\n```\n\n## Migration Timeline\n\n```\nPhase 1: Setup (1-2 weeks)\n- Install Angular CLI\n- Set up hybrid app\n- Configure build tools\n- Set up testing\n\nPhase 2: Infrastructure (2-4 weeks)\n- Migrate services\n- Migrate utilities\n- Set up routing\n- Migrate shared components\n\nPhase 3: Feature Migration (varies)\n- Migrate feature by feature\n- Test thoroughly\n- Deploy incrementally\n\nPhase 4: Cleanup (1-2 weeks)\n- Remove AngularJS code\n- Remove ngUpgrade\n- Optimize bundle\n- Final testing\n```\n\n## Resources\n\n- **references\u002Fhybrid-mode.md**: Hybrid app patterns\n- **references\u002Fcomponent-migration.md**: Component conversion guide\n- **references\u002Fdependency-injection.md**: DI migration strategies\n- **references\u002Frouting.md**: Routing migration\n- **assets\u002Fhybrid-bootstrap.ts**: Hybrid app template\n- **assets\u002Fmigration-timeline.md**: Project planning\n- **scripts\u002Fanalyze-angular-app.sh**: App analysis script\n\n## Best Practices\n\n1. **Start with Services**: Migrate services first (easier)\n2. **Incremental Approach**: Feature-by-feature migration\n3. **Test Continuously**: Test at every step\n4. **Use TypeScript**: Migrate to TypeScript early\n5. **Follow Style Guide**: Angular style guide from day 1\n6. **Optimize Later**: Get it working, then optimize\n7. **Document**: Keep migration notes\n\n## Common Pitfalls\n\n- Not setting up hybrid app correctly\n- Migrating UI before logic\n- Ignoring change detection differences\n- Not handling scope properly\n- Mixing patterns (AngularJS + Angular)\n- Inadequate testing\n",{"name":5,"risk":34,"source":28,"date_added":35,"description":7},"unknown","2026-02-27","main","a50a3aa6b39fb0e1b7db88bef1bfc9c93606e126","modules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fangular-migration",0,"https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant","https:\u002F\u002Fgithub.com\u002FSam-06060","Mobile Application Developer | Kotlin | Flutter, KMP, Swfit, Android,Swift UI | Building at Saar It Resources | Creator of Jarvis (AI Assistant)","2026-06-23 05:13:38",{"source":8,"skillName":5,"commands":45,"prompt":55,"zipAvailable":56},[46,49,52],{"tool":47,"command":48},"npx","npx skills add Sam-06060\u002Fjarvis-assistant --skill angular-migration",{"tool":50,"command":51},"bunx","bunx skills add Sam-06060\u002Fjarvis-assistant --skill angular-migration",{"tool":53,"command":54},"pnpm","pnpm dlx skills add Sam-06060\u002Fjarvis-assistant --skill angular-migration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fangular-migration\u002FSKILL.md",true,[],[59,72,88,115,134,161],{"skillNo":60,"name":61,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":62,"categories":63,"keywords":69,"publishedAt":29},"01M6GDRVS6FXX3ESH0C9DW01C0","test_skill","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fscratch\u002Ftest_skill\u002FSKILL.md",[64],{"categoryNo":65,"categoryName":66,"taxonomyType":67,"taxonomyTypeDesc":68},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[70,71],"Test Skill","test",{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":78,"publishedAt":29},"01M6GDRQ40HX22MA6XWC31RHHK","zustand-store-ts","Create Zustand stores following established patterns with proper TypeScript types and middleware.","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fzustand-store-ts\u002FSKILL.md",[],[79,80,81,82,83,84,85,28,86,87],"zustand store ts","zustand","store","with","types","middleware","patterns","create","typescript",{"skillNo":89,"name":90,"nameZh":6,"description":91,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":97,"publishedAt":29},"01M6GDRKEA0WE670SPFWX5GKCN","zoom-automation","Automate Zoom meeting creation, management, recordings, webinars, and participant tracking via Rube MCP (Composio). Always search tools first for current schemas.","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fzoom-automation\u002FSKILL.md",[94],{"categoryNo":95,"categoryName":96,"taxonomyType":67,"taxonomyTypeDesc":68},"01JBSEEDCAT000000000000023","Skill与智能体开发",[98,99,100,101,102,103,104,105,106,107,108,109,110,111,28,112,113,114],"automation","zoom automation","zoom","first","Tools","search","MCP","via","meeting","automate","critical","creation","webinars","composio","recordings","management","tracking",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":122,"publishedAt":29},"01M6GDRFS1452PC71JQ38S24HR","zoho-crm-automation","Automate Zoho CRM tasks via Rube MCP (Composio): create\u002Fupdate records, search contacts, manage leads, and convert leads. Always search tools first for current schemas.","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fzoho-crm-automation\u002FSKILL.md",[121],{"categoryNo":95,"categoryName":96,"taxonomyType":67,"taxonomyTypeDesc":68},[123,98,124,125,126,127,128,28,103,129,111,130,108,107,102,131,86,132,104,133],"crm automation","zoho crm","crm","zoho crm automation","zoho","leads","contacts","records","update","tasks","manage",{"skillNo":135,"name":136,"nameZh":6,"description":137,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":138,"categories":139,"keywords":143,"publishedAt":29},"01M6GDRCKQBAVTGHX5XBH26KPZ","zod-validation-expert","Expert in Zod — TypeScript-first schema validation. Covers parsing, custom errors, refinements, type inference, and integration with React Hook Form, Next.js, and tRPC.","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fzod-validation-expert\u002FSKILL.md",[140],{"categoryNo":141,"categoryName":142,"taxonomyType":67,"taxonomyTypeDesc":68},"01JBSEEDCAT000000000000009","前端开发",[144,145,146,147,148,87,149,150,151,152,153,154,82,155,156,157,158,28,159,160],"expert","zod","zod validation expert","validation","react","safe","parsing","errors","schema validation","react hook form","hook","trpc","form","type","next","schema","Next.js",{"skillNo":162,"name":163,"nameZh":6,"description":164,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":165,"categories":166,"keywords":168,"publishedAt":29},"01M6GDR658B08K4MY0RWD4A6EH","zeroize-audit","Detects missing zeroization of sensitive data in source code and identifies zeroization removed by compiler optimizations, with assembly-level analysis, and control-flow verification. Use for auditing C\u002FC++\u002FRust code handling secrets, keys, passwords, or other sensitive data.","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fzeroize-audit\u002FSKILL.md",[167],{"categoryNo":95,"categoryName":96,"taxonomyType":67,"taxonomyTypeDesc":68},[169,170,171,172,173,174,175,176,28,177,178,179,180,181,182,183,184,185,186,104],"zeroize audit","audit","write","passwords","get","project","c++","activate","assembly","read","Bash","secrets","analysis","data","flow","verification","code","rust"]