{"id":2429,"date":"2017-04-09T16:01:34","date_gmt":"2017-04-09T14:01:34","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=2429"},"modified":"2017-04-09T16:01:34","modified_gmt":"2017-04-09T14:01:34","slug":"directly-upgrading-from-angularjs-1-x","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/","title":{"rendered":"Directly Upgrading From AngularJS 1.X"},"content":{"rendered":"<div class=\"article\">\n<p>When upgrading from AngularJS 1.x to Angular (2\/4\/5 etc.), we usually prepare our AngularJS 1.x code base first:<\/p>\n<p><a href=\"https:\/\/camo.githubusercontent.com\/04aee72847c1e24693a71a2a678a1b67a83e8a29\/687474703a2f2f692e696d6775722e636f6d2f43416f38725a322e706e67\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/camo.githubusercontent.com\/04aee72847c1e24693a71a2a678a1b67a83e8a29\/687474703a2f2f692e696d6775722e636f6d2f43416f38725a322e706e67\" alt=\"\" data-canonical-src=\"http:\/\/i.imgur.com\/CAo8rZ2.png\" style=\"max-width:100%;\"><\/a><\/p>\n<p>This can involve leveraging new AngularJS 1.x techniques like components. Additionally, introducing TypeScript as well as module loaders like SystemJS or webpack are further tasks to prepare the existing code. The goal behind this is to draw near Angular in order to allow a better integration.<\/p>\n<p>But in some situations preparing the existing code is too costly. For instance, think about situations where we just want to write new parts of the application with Angular without the need to modify much of the existing AngularJS 1.x code. When this holds true for your project, skipping the preparation phase could be a good idea:<\/p>\n<p><a href=\"https:\/\/camo.githubusercontent.com\/28739213e9972a9586fc3a66017c7502d7d55d26\/687474703a2f2f692e696d6775722e636f6d2f614b6b4d66666e2e706e67\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/camo.githubusercontent.com\/28739213e9972a9586fc3a66017c7502d7d55d26\/687474703a2f2f692e696d6775722e636f6d2f614b6b4d66666e2e706e67\" alt=\"\" data-canonical-src=\"http:\/\/i.imgur.com\/aKkMffn.png\" style=\"max-width:100%;\"><\/a><\/p>\n<p>This post shows step by step, how this approach can be accomplished. Like the <a href=\"https:\/\/angular.io\/guide\/upgrade\">official and well written upgrading tutorial<\/a> which includes preparing the code base, it upgrades the popular <a href=\"https:\/\/github.com\/angular\/angular-phonecat\">AngularJS 1.x Phone Catalog Sample<\/a>.<\/p>\n<p>Even though this sample leverages AngularJS components introduced with AngularJS 1.5, everything shown here also works with more \"traditional\" AngularJS code using controllers and directives.<\/p>\n<p>The <a href=\"https:\/\/github.com\/manfredsteyer\/ngUpgrade-without-preparation\">whole sample<\/a> can be found in <a href=\"https:\/\/github.com\/manfredsteyer\/ngUpgrade-without-preparation\">my GitHub repository<\/a>. In order to make following everything easier, I've also created one commit for each of the steps described here.<\/p>\n<h2>Step 1: Creating the new Angular Application<\/h2>\n<p>As a starting point this article assumes that we are scaffolding a new Angular application with the <a href=\"https:\/\/cli.angular.io\/\">Angular CLI<\/a>:<\/p>\n<pre><code>ng new migrated\n<\/code><\/pre>\n<p>To make the structure of this new solution clearer, create one folder for the existing AngularJS code and another one for the new Angular code within <code>src<\/code>. In the sample presented here, I've used the names <code>ng1<\/code> and <code>ng2<\/code>:<\/p>\n<p><a href=\"https:\/\/camo.githubusercontent.com\/9a878a733d49cfef869dbca00945160024c787f9\/687474703a2f2f692e696d6775722e636f6d2f776736543434422e706e67\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/camo.githubusercontent.com\/9a878a733d49cfef869dbca00945160024c787f9\/687474703a2f2f692e696d6775722e636f6d2f776736543434422e706e67\" alt=\"\" data-canonical-src=\"http:\/\/i.imgur.com\/wg6T44B.png\" style=\"max-width:100%;\"><\/a><\/p>\n<p>After this, move every generated file <strong>except<\/strong> the shown <code>tsconfig.app.json<\/code>, <code>tsconfig.spec.json<\/code>, <code>favicon.ico<\/code> and <code>index.html<\/code> into the <code>ng2<\/code> folder.<\/p>\n<p>To inform the CLI's build task about this new structure, adopt the file <code>.angular-cli.json<\/code>. Using the <code>assets<\/code> section in this file, we can also tell the CLI to directly copy the <code>ng1<\/code> folder to the output directory:<\/p>\n<pre><code>{\n  \"$schema\": \".\/node_modules\/@angular\/cli\/lib\/config\/schema.json\",\n  \"project\": {\n    \"name\": \"migrated\"\n  },\n  \"apps\": [\n    {\n      \"root\": \"src\",\n      \"outDir\": \"dist\",\n      \"assets\": [\n        \"ng1\",\n        \"assets\",\n        \"favicon.ico\"\n      ],\n      \"index\": \"index.html\",\n      \"main\": \"ng2\/main.ts\",\n      \"polyfills\": \"ng2\/polyfills.ts\",\n      \"test\": \"ng2\/test.ts\",\n      \"tsconfig\": \"tsconfig.app.json\",\n      \"testTsconfig\": \"tsconfig.spec.json\",\n      \"prefix\": \"app\",\n      \"styles\": [\n        \"ng2\/styles.css\"\n      ],\n      \"scripts\": [],\n      \"environmentSource\": \"ng2\/environments\/environment.ts\",\n      \"environments\": {\n        \"dev\": \"ng2\/environments\/environment.ts\",\n        \"prod\": \"ng2\/environments\/environment.prod.ts\"\n      }\n    }\n  ],\n  \"e2e\": {\n    \"protractor\": {\n      \"config\": \".\/protractor.conf.js\"\n    }\n  },\n  \"lint\": [\n    {\n      \"project\": \"tsconfig.app.json\"\n    },\n    {\n      \"project\": \"tsconfig.spec.json\"\n    },\n    {\n      \"project\": \"tsconfig.e2e.json\"\n    }\n  ],\n  \"test\": {\n    \"karma\": {\n      \"config\": \".\/karma.conf.js\"\n    }\n  },\n  \"defaults\": {\n    \"styleExt\": \"css\",\n    \"component\": {}\n  }\n}\n<\/code><\/pre>\n<p>Now copy the whole AngularJS 1.x application into the <code>ng1<\/code> folder but <strong>omit<\/strong> it's <code>index.html<\/code>. To make the existing application work with the adopted folder structure, we have to update it. This involves  updating every reference to a template as well as references to JSON files and images.<\/p>\n<p>After this, we can merge the existing <code>index.html<\/code> with the new one in the folder <code>src<\/code>:<\/p>\n<pre><code>&lt;!doctype html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n  &lt;meta charset=\"utf-8\"&gt;\n  &lt;title&gt;Migrated&lt;\/title&gt;\n  &lt;base href=\"\/\"&gt;\n\n  &lt;!-- ng1 --&gt;\n  &lt;link rel=\"stylesheet\" href=\"ng1\/bower_components\/bootstrap\/dist\/css\/bootstrap.css\" \/&gt;\n  &lt;link rel=\"stylesheet\" href=\"ng1\/app.css\" \/&gt;\n  &lt;link rel=\"stylesheet\" href=\"ng1\/app.animations.css\" \/&gt;\n\n  &lt;script src=\"ng1\/bower_components\/jquery\/dist\/jquery.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/bower_components\/angular\/angular.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/bower_components\/angular-animate\/angular-animate.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/bower_components\/angular-resource\/angular-resource.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/bower_components\/angular-route\/angular-route.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/app.module.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/app.config.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/app.animations.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/core\/core.module.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/core\/checkmark\/checkmark.filter.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/core\/phone\/phone.module.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/core\/phone\/phone.service.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/phone-list\/phone-list.module.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/phone-list\/phone-list.component.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/phone-detail\/phone-detail.module.js\"&gt;&lt;\/script&gt;\n  &lt;script src=\"ng1\/phone-detail\/phone-detail.component.js\"&gt;&lt;\/script&gt;\n  &lt;!-- \/ng1 --&gt;\n\n  &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;\n  &lt;link rel=\"icon\" type=\"image\/x-icon\" href=\"favicon.ico\"&gt;\n&lt;\/head&gt;\n&lt;body ng-app=\"phonecatApp\"&gt;\n\n  &lt;!-- ng1 --&gt;\n  &lt;div class=\"view-container\"&gt;\n      &lt;div ng-view class=\"view-frame\"&gt;&lt;\/div&gt;\n  &lt;\/div&gt;\n  &lt;!-- \/ng1 --&gt;\n\n  &lt;app-root&gt;&lt;\/app-root&gt;\n\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n<p>Note that this merged <code>index.html<\/code> contains references to the CSS files and scripts the AngularJS 1.x application needs. It also bootstraps the AngularJS 1.x application using <code>ng-app<\/code> and provides its shell containing a <code>div<\/code> with the <code>ng-view<\/code> directive. This is where the router activates the configured templates.<\/p>\n<p>In this file we can also find the root element for our Angular application. References to the generated Angular bundles are not necessary as they are generated by the build task.<\/p>\n<p>When this application is started (<code>ng serve<\/code>), it loads both applications independently of each other into the browser. To see this, navigate to <code>http:\/\/localhost:4200<\/code>:<\/p>\n<p><a href=\"https:\/\/camo.githubusercontent.com\/5b69a4c687cabe92e749303c0db8067fcc5ac69a\/687474703a2f2f692e696d6775722e636f6d2f307674424f46572e706e67\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/camo.githubusercontent.com\/5b69a4c687cabe92e749303c0db8067fcc5ac69a\/687474703a2f2f692e696d6775722e636f6d2f307674424f46572e706e67\" alt=\"\" data-canonical-src=\"http:\/\/i.imgur.com\/0vtBOFW.png\" style=\"max-width:100%;\"><\/a><\/p>\n<p>As those two applications are bootstrapped separately, they are not able to communicated with each other or to exchange services and components. To make this work, we have to bootstrap them together as a hybrid application. The next section show how to do this.<\/p>\n<h2>Step 2: Bootstrap an AngularJS+Angular Hybrid Application<\/h2>\n<p>To bootstrap one application with both, AngularJS 1.x and Angular, we can leverage ngUpgrade which is part of Angular:<\/p>\n<pre><code>npm install @angular\/upgrade --save\n<\/code><\/pre>\n<p>As we don't want to bootstrap the Angular (2\/4\/5 etc.) application on its own, we remove it's root component within the <code>index.html<\/code>:<\/p>\n<pre><code>&lt;!-- remove root component --&gt;\n&lt;!--\n    &lt;app-root&gt;&lt;\/app-root&gt;\n--&gt;\n<\/code><\/pre>\n<p>Now, we can bootstrap both applications together. For this, import the <code>UpgradeModule<\/code> into the Angular application's <code>AppModule<\/code>. Remove the <code>AppComponent<\/code> from <code>bootstrap<\/code> in order to bootstrap the hybrid application manually:<\/p>\n<pre><code>import { BrowserModule } from '@angular\/platform-browser';\nimport { NgModule } from '@angular\/core';\nimport { UpgradeModule, downgradeComponent } from '@angular\/upgrade\/static';\nimport { AppComponent } from '.\/app.component';\nimport { Ng2DemoComponent } from \"ng2\/app\/ng2-demo.component\";\n\n@NgModule({\n  declarations: [\n    AppComponent\n  ],\n  imports: [\n    BrowserModule,\n    UpgradeModule\n  ],\n  providers: [],\n  \/\/ bootstrap: [AppComponent] \/\/ No Bootstrap-Component\n})\nexport class AppModule {\n  constructor(private upgrade: UpgradeModule) { }\n  ngDoBootstrap() {\n    this.upgrade.bootstrap(document.body, ['phonecatApp'], { strictDi: true });\n  }\n}\n<\/code><\/pre>\n<p>As you can see here, this example bootstraps the hybrid application within <code>ngDoBootstrap<\/code> using the injected <code>UpgradeModule<\/code>. To prevent bootstrapping the AngularJS 1.x part twice, we have to <strong>remove<\/strong> the <code>ng-app<\/code> directive within the file <code>index.html<\/code>.<\/p>\n<p>When we start the application after this, we just see the AngularJS 1.x components:<\/p>\n<p><a href=\"https:\/\/camo.githubusercontent.com\/2b1c8295177960d59c052969d5cc526caeb036ad\/687474703a2f2f692e696d6775722e636f6d2f457a35376a4f592e706e67\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/camo.githubusercontent.com\/2b1c8295177960d59c052969d5cc526caeb036ad\/687474703a2f2f692e696d6775722e636f6d2f457a35376a4f592e706e67\" alt=\"\" data-canonical-src=\"http:\/\/i.imgur.com\/Ez57jOY.png\" style=\"max-width:100%;\"><\/a><\/p>\n<p>Nevertheless, it's a hybrid application with both versions of Angular. To proof this, the next section shows how to use an Angular component within the shown AngularJS component.<\/p>\n<h2>Step 3: Downgrading an Angular Component<\/h2>\n<p>To show how to use an Angular Component within our hybrid application's AngularJS context, this tutorial uses a very simple dummy component:<\/p>\n<pre><code>\/\/ src\/app\/ng2-demo.component.ts\n\nimport { Component, OnInit } from '@angular\/core';\n\n@Component({\n  selector: 'ng2-demo',\n  template: `\n    &lt;h3&gt;Angular 2 Demo Component&lt;\/h3&gt;\n    &lt;img width=\"150\" src=\"...\" \/&gt;\n  `\n})\nexport class Ng2DemoComponent  {\n}\n<\/code><\/pre>\n<p>The source for the shown image can be found in scaffolded <code>AppComponent<\/code>.<\/p>\n<p>To use this component within an AngularJS template, we have to downgrade it. For this, ngUpgrade provides the function <code>downgradeComponent<\/code>:<\/p>\n<pre><code>import { BrowserModule } from '@angular\/platform-browser';\nimport { NgModule } from '@angular\/core';\nimport { UpgradeModule, downgradeComponent } from '@angular\/upgrade\/static';\nimport { AppComponent } from '.\/app.component';\nimport { Ng2DemoComponent } from \"ng2\/app\/ng2-demo.component\";\n\ndeclare var angular: any;\n\nangular.module('phonecatApp')\n  .directive(\n    'ng2Demo',\n    downgradeComponent({component: Ng2DemoComponent})\n  );\n\n@NgModule({\n  declarations: [\n    AppComponent,\n    Ng2DemoComponent\n  ],\n  imports: [\n    BrowserModule,\n    UpgradeModule\n  ],\n  entryComponents: [\n    Ng2DemoComponent \/\/ Don't forget this!!!\n  ],\n  providers: [],\n  \/\/ bootstrap: [AppComponent] \/\/ No Bootstrap-Component\n})\nexport class AppModule {\n  constructor(private upgrade: UpgradeModule) { }\n  ngDoBootstrap() {\n    this.upgrade.bootstrap(document.body, ['phonecatApp'], { strictDi: true });\n  }\n}\n<\/code><\/pre>\n<p>As you see in this sample, the downgraded component is registered as a directive within the AngularJS 1.x module. For this, we can leverage the global <code>angular<\/code> variable. In order to tell TypeScript about this preexisting variable, we have to use the <code>declare<\/code> keyword.<\/p>\n<p>After this, we can call the Angular Component within an AngularJS 1.x template:<\/p>\n<pre><code>  &lt;!-- src\/ng1\/phone-list\/phone-list.template.html --&gt;\n\n  &lt;div class=\"row\"&gt;\n    &lt;div class=\"col-md-2\"&gt;\n      &lt;!--Sidebar content--&gt;\n\n      &lt;p&gt;\n        Search:\n        &lt;input ng-model=\"$ctrl.query\" \/&gt;\n      &lt;\/p&gt;\n\n      &lt;p&gt;\n        Sort by:\n        &lt;select ng-model=\"$ctrl.orderProp\"&gt;\n          &lt;option value=\"name\"&gt;Alphabetical&lt;\/option&gt;\n          &lt;option value=\"age\"&gt;Newest&lt;\/option&gt;\n        &lt;\/select&gt;\n      &lt;\/p&gt;\n\n      &lt;p&gt;\n\n        &lt;!-- Angular 2 Component --&gt;\n        &lt;ng2-demo&gt;&lt;\/ng2-demo&gt;\n\n      &lt;\/p&gt;\n\n    &lt;\/div&gt;\n<\/code><\/pre>\n<p>As usual in AngularJS, we have to make use of kebab case within HTML files while we have to register the directive with its normalized name the JavaScript counterpart. The latter one is using camel case.<\/p>\n<p>When we reload the application, it shows the AngularJS 1.x phone list with our Angular demo component:<\/p>\n<p><a href=\"https:\/\/camo.githubusercontent.com\/fda1c4da1842689d2696cc2b6f83d959e5bbc886\/687474703a2f2f692e696d6775722e636f6d2f594c4e7a5574312e706e67\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/camo.githubusercontent.com\/fda1c4da1842689d2696cc2b6f83d959e5bbc886\/687474703a2f2f692e696d6775722e636f6d2f594c4e7a5574312e706e67\" alt=\"\" data-canonical-src=\"http:\/\/i.imgur.com\/YLNzUt1.png\" style=\"max-width:100%;\"><\/a><\/p>\n<p>Perhaps you are wondering how this new Anglar Component can use the existing application logic provided by AngularJS 1.x services. Read the next section to get an answer.<\/p>\n<h2>Step 4: Upgrade a service<\/h2>\n<p>In order to use an existing AngularJS 1.x service within a new Angular Component, we have to upgrade it. According to the official docs, we have to create an Angular service provider which uses a factory. This factory gets a reference to the AngularJS 1.x injector (<code>$injector<\/code>) and uses it to obtain the service in question:<\/p>\n<pre><code>\/\/ src\/ng2\/app\/phone.service.ts\n\nimport { InjectionToken } from \"@angular\/core\";\n\nexport const PHONE_SERVICE = new InjectionToken&lt;any&gt;('PHONE_SERVICE');\n\nexport function createPhoneService(i) {\n  return i.get('Phone');\n}\n\nexport const phoneServiceProvider = {\n  provide: PHONE_SERVICE,\n  useFactory: createPhoneService,\n  deps: ['$injector']\n}\n<\/code><\/pre>\n<p>Normally, we could use the service's type as the dependency injection token defined by the <code>provide<\/code> property. But in this case we explicitly decided to not upgrade the existing AngularJS 1.x code to TypeScript and so we don't have any type for it. Because of this, this sample uses a constant based Token called <code>PHONE_SERVICE<\/code>. For such tokens Angular 4+ provides the type <code>InjectionToken<\/code>. In Angular 2 we would use <code>OpaqueToken<\/code> instead. The <code>InjectionToken<\/code> takes a type parameter which identifies the type of the service it is pointing to. As mentioned, we don't have a type for this service and so we are just going with <code>any<\/code>.<\/p>\n<p>The discussed service provider has to be registered with our Angular module:<\/p>\n<pre><code>\/\/ src\/ng2\/app\/app.module.ts\n\n[...]\nimport { phoneServiceProvider } from \"ng2\/app\/phone.service\";\n\n[...]\n\n@NgModule({\n  [...],\n  providers: [\n    phoneServiceProvider\n  ]\n})\nexport class AppModule {\n  [...]\n}\n<\/code><\/pre>\n<p>After this, we can inject the <code>phoneService<\/code> into our <code>Ng2DemoComponent<\/code> and use it to load all managed phones:<\/p>\n<pre><code>import { Component, OnInit, Inject } from '@angular\/core';\nimport { PHONE_SERVICE } from \"ng2\/app\/phone.service\";\n\n@Component({\n  selector: 'ng2-demo',\n  template: `\n    &lt;h3&gt;Angular 2 Demo Component&lt;\/h3&gt;\n    &lt;img width=\"150\" src=\"[...]\" \/&gt;\n    &lt;p&gt;\n      {{phones.length}} Phones found.\n    &lt;\/p&gt;\n  `\n})\nexport class Ng2DemoComponent implements OnInit {\n\n  phones: any[] = [];\n\n  constructor(\n    @Inject(PHONE_SERVICE) private phoneService: any) {\n    }\n\n    ngOnInit() {\n      this.phones = this.phoneService.query();\n    }\n\n}\n<\/code><\/pre>\n<p>As our token is just a constant, this sample uses the <code>Inject<\/code> decorator which points to it. After loading the phones, it just displays their count.<\/p>\n<p>After reloading the application we see can this:<\/p>\n<p><a href=\"https:\/\/camo.githubusercontent.com\/9a78b982078a3f2a9720686a996e60fbe33e9eda\/687474703a2f2f692e696d6775722e636f6d2f756c38306175782e706e67\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/camo.githubusercontent.com\/9a78b982078a3f2a9720686a996e60fbe33e9eda\/687474703a2f2f692e696d6775722e636f6d2f756c38306175782e706e67\" alt=\"\" data-canonical-src=\"http:\/\/i.imgur.com\/ul80aux.png\" style=\"max-width:100%;\"><\/a><\/p>\n<p>Please note that we have an AngularJS 1.x component with an Angular Component that is displaying data from an AngularJS 1.x service.<\/p>\n<p>Instead of nesting AngularJS 1.x and Angular stuff, we also need the possibility to activate routes from both versions. The next sections deal with this.<\/p>\n<h2>Step 5: Routing to Angular Components<\/h2>\n<p>Making the AngularJS 1.x Router to activate Angular components is quite easy. For this, we just have to configure a route with a template that points to the component in question:<\/p>\n<pre><code>$routeProvider.\n  when('\/phones', {\n    template: '&lt;phone-list&gt;&lt;\/phone-list&gt;'   \/\/ AngularJS 1.x template \n  }).\n  when('\/phones\/:phoneId', {\n    template: '&lt;phone-detail&gt;&lt;\/phone-detail&gt;' \/\/ AngularJS 1.x template \n  }).\n  when('\/ng2-demo', {\n    template: '&lt;ng2-demo&gt;&lt;\/ng2-demo&gt;' \/\/ Angular component\n  })\n<\/code><\/pre>\n<p>This allows to use the Angular Component alongside AngularJS routes which can base upon traditional controllers as well as directives and components.<\/p>\n<p>I want to strike out, that this very approach works with the popular UI-Router too.<\/p>\n<p>While this solution is very easy, it also comes with a drawback: We cannot leverage the new Angular Router for the newly written components. To make this possible, we can implement Victor Savkin's <a href=\"https:\/\/blog.nrwl.io\/upgrading-angular-applications-managing-routers-and-url-ca5588290aaa\">Sibling Outlet approach<\/a>, which uses both routers together. To foundation for this is his <a href=\"https:\/\/blog.nrwl.io\/upgrading-angular-applications-upgrade-shell-4d4f4a7e7f7b\">Upgrade Shell pattern<\/a>.    The next two sections describe how to introduce those ideas into the case study presented here.<\/p>\n<h2>Step 6: Using Victor Savkin's Upgrade Shell pattern<\/h2>\n<p>The upgrade shell pattern has been introduced by Victor Savkin who one of the masterminds behind Angular. He describes it in <a href=\"https:\/\/blog.nrwl.io\/upgrading-angular-applications-upgrade-shell-4d4f4a7e7f7b\">his blog<\/a> as well in his <a href=\"https:\/\/leanpub.com\/ngupgrade\">eBook about ngUpgrade<\/a>. It envisages an Angular component on top of an hybrid application. This is the upgrade shell that contains both, AngularJS building blocks (directives, components, controllers) as well as Angular Components.<\/p>\n<p>To implement this pattern we can use the <code>AppComponent<\/code> the CLI generated when we started the endeavor described in this article:<\/p>\n<pre><code>\/\/ src\/ng2\/app\/app.component.html\n&lt;!--The whole content below can be removed with the new code.--&gt;\n&lt;div style=\"text-align:center\"&gt;\n  &lt;h1&gt;\n    Welcome to {{title}}!!\n  &lt;\/h1&gt;\n\n&lt;\/div&gt;\n\n&lt;!-- ng1 --&gt;\n&lt;div class=\"view-container\"&gt;\n    &lt;div ng-view class=\"view-frame\"&gt;&lt;\/div&gt;\n&lt;\/div&gt;\n&lt;!-- \/ng1 --&gt;\n<\/code><\/pre>\n<p>Note that this Angular components contains the <code>ng-view<\/code> for the AngularJS 1.x router.<\/p>\n<p>To make this component the top level component of our application, we have to directly bootstrap it. For this, we have to put it into the <code>bootstrap<\/code> array of the <code>AppModule<\/code>:<\/p>\n<pre><code>\/\/ src\/ng2\/app\/app.module.ts\n\nimport { BrowserModule } from '@angular\/platform-browser';\nimport { NgModule, InjectionToken } from '@angular\/core';\nimport { UpgradeModule, downgradeComponent } from '@angular\/upgrade\/static';\nimport { AppComponent } from '.\/app.component';\nimport { Ng2DemoComponent } from \"ng2\/app\/ng2-demo.component\";\nimport { phoneServiceProvider } from \"ng2\/app\/phone.service\";\n\ndeclare var angular: any;\n\nangular.module('phonecatApp')\n  .directive(\n    'ng2Demo',\n    downgradeComponent({component: Ng2DemoComponent})\n  );\n\n@NgModule({\n  declarations: [\n    AppComponent,\n    Ng2DemoComponent\n  ],\n  imports: [\n    BrowserModule,\n    UpgradeModule\n  ],\n  entryComponents: [\n    Ng2DemoComponent \/\/ Don't forget this!!!\n  ],\n  providers: [\n    phoneServiceProvider\n  ],\n  bootstrap: [AppComponent]\n})\n\nexport class AppModule {\n\/\/ Remove code for bootstrapping hybrid app manually !!!\n\/*\n  constructor(private upgrade: UpgradeModule) { }\n  ngDoBootstrap() {\n    this.upgrade.bootstrap(document.body, ['phonecatApp'], { strictDi: true });\n  }\n*\/\n}\n<\/code><\/pre>\n<p>Please note, that we also have to remove the code to bootstrap the application manually. This code is moved into the <code>AppComponent<\/code> and does it's job after the upgrade shell has been bootstrapped:<\/p>\n<pre><code>\/\/ src\/ng2\/app\/app.component.ts\n\nimport { Component, Inject } from '@angular\/core';\nimport { PHONE_SERVICE } from \"ng2\/app\/phone.service\";\nimport { UpgradeModule } from \"@angular\/upgrade\/static\";\n\n@Component({\n  selector: 'app-root',\n  templateUrl: '.\/app.component.html',\n  styleUrls: ['.\/app.component.css']\n})\nexport class AppComponent {\n  title = 'app';\n\n   phones: any[] = [];\n\n   constructor(private upgrade: UpgradeModule) { }\n\n    ngOnInit() {\n      this.upgrade.bootstrap(document.body, ['phonecatApp']);\n    }\n}\n<\/code><\/pre>\n<p>Also, make sure that the <code>index.html<\/code> is just referencing our upgrade shell:<\/p>\n<pre><code>&lt;!-- src\/index.html --&gt;\n&lt;body&gt;\n  &lt;app-root&gt;&lt;\/app-root&gt;\n&lt;\/body&gt;\n<\/code><\/pre>\n<p>Reload the application and see the upgrade shell which contains the AngularJS 1.x application.<\/p>\n<p>When this works, we have provided the foundation for the goal of the next section: Using both, the AngularJS 1.x as well the Angular router, alongside.<\/p>\n<h2>Step 7: Using Victor Savkin's Sibling Outlet approach to use both Routers<\/h2>\n<p>[Victor's sibling outlet approach]((<a href=\"https:\/\/blog.nrwl.io\/upgrading-angular-applications-managing-routers-and-url-ca5588290aaa\">https:\/\/blog.nrwl.io\/upgrading-angular-applications-managing-routers-and-url-ca5588290aaa<\/a>) describes a way to use routers of both Angular versions alongside. To implement it, we need to load the Angular router:<\/p>\n<pre><code>npm install @angular\/router --save\n<\/code><\/pre>\n<p>After this, extend the <code>app.component.html<\/code>. It gets one outlet for each router version. For the AngularJS 1.x router it's a <code>div<\/code> with the <code>ng-view<\/code> directive. For the Angular Router it's a <code>router-outlet<\/code> element:<\/p>\n<pre><code>&lt;!-- src\/ng2\/app\/app.component.html --&gt;\n&lt;div class=\"view-container\"&gt;\n    &lt;div ng-view class=\"view-frame\"&gt;&lt;\/div&gt;\n    &lt;router-outlet&gt;&lt;\/router-outlet&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n<p>When activating an AngularJS 1. based route, the first one gets a template; when activating an Angular route the latter one is used.<\/p>\n<p>Now, let's configure the Angular router:<\/p>\n<pre><code>\/\/ src\/ng2\/app\/app.module.ts\n\nimport { BrowserModule } from '@angular\/platform-browser';\nimport { NgModule, InjectionToken } from '@angular\/core';\nimport { RouterModule} from '@angular\/router';\n\nimport { UpgradeModule, downgradeComponent } from '@angular\/upgrade\/static';\nimport { AppComponent } from '.\/app.component';\nimport { Ng2DemoComponent } from \"ng2\/app\/ng2-demo.component\";\nimport { phoneServiceProvider } from \"ng2\/app\/phone.service\";\n\ndeclare var angular: any;\n\nangular.module('phonecatApp')\n  .directive(\n    'ng2Demo',\n    downgradeComponent({component: Ng2DemoComponent})\n  );\n\n@NgModule({\n  declarations: [\n    AppComponent,\n    Ng2DemoComponent\n  ],\n  imports: [\n    BrowserModule,\n    UpgradeModule,\n    RouterModule.forRoot([\n      {\n        path: '',\n        pathMatch: 'full',\n        redirectTo: 'ng2-route'\n\n      },\n      {\n        path: 'ng2-route',\n        component: Ng2DemoComponent\n      }\n    ],\n    {\n      useHash: true\n    }\n    )\n  ],\n  entryComponents: [\n    Ng2DemoComponent\n  ],\n  providers: [\n    phoneServiceProvider\n  ],\n  bootstrap: [AppComponent]\n})\n\nexport class AppModule {\n}\n<\/code><\/pre>\n<p>As you can see here, the configuration for the Angular router just defines two routes in this example. In addition to this, is is using the hash strategy for the sake of uniformity between the two versions.<\/p>\n<p>We also have to make sure that the Angular router is doing nothing when a AngularJS 1.x route is activated. For this, Victor proposes the use of a custom <code>UrlHandlingStrategy<\/code>:<\/p>\n<pre><code>\/\/ src\/ng2\/app\/app.module.ts\n\nimport { RouterModule, UrlHandlingStrategy } from '@angular\/router';\n\n[...]\n\nexport class CustomHandlingStrategy implements UrlHandlingStrategy {\n  shouldProcessUrl(url) {\n    return url.toString().startsWith(\"\/ng2-route\") || url.toString() === \"\/\";\n  }\n  extract(url) { return url; }\n  merge(url, whole) { return url; }\n}\n<\/code><\/pre>\n<p>This strategy has to be registered, e. g. with the <code>AppModule<\/code>:<\/p>\n<pre><code>\/\/ src\/ng2\/app\/app.module.ts\n@NgModule({\n  [...]\n  providers: [\n    phoneServiceProvider,\n    { provide: UrlHandlingStrategy, useClass: CustomHandlingStrategy }\n  ],\n  bootstrap: [AppComponent]\n})\nexport class AppModule {\n}\n<\/code><\/pre>\n<p>After this, we have to modify the AngularJS 1.x routing configuration a bit. First of all, we have to remove the configured hash prefix because this would irritate the Angular router. In addition to this, we have to add a default route using <code>otherwise<\/code> that loads an empty template into the version-1-outlet when the route in question is handled by the other router:<\/p>\n<pre><code>\/\/ src\/app1\/app.config.js\n\n\/\/ No Prefix for the sake of uniformity\n\/\/ $locationProvider.hashPrefix('!');\n\n$routeProvider.\n  when('\/phones', {\n    template: '&lt;phone-list&gt;&lt;\/phone-list&gt;'\n  }).\n  when('\/phones\/:phoneId', {\n    template: '&lt;phone-detail&gt;&lt;\/phone-detail&gt;'\n  }).\n  when('\/ng2-demo', {\n    template: '&lt;ng2-demo&gt;&lt;\/ng2-demo&gt;'\n  })\n  .otherwise({template : ''});\n<\/code><\/pre>\n<p>As above, everything shown using the AngularJS 1.x router also works the the popular UI-Router.<\/p>\n<p>After this, just add some kind of menu to the <code>AppComponent<\/code> that allows to switch between the AngularJS 1.x based as well as Angular based routes:<\/p>\n<pre><code>&lt;!-- src\/app2\/app.component.html --&gt;\n\n&lt;a routerLink=\"ng2-route\"&gt;ng2-route&lt;\/a&gt; |\n&lt;a href=\"#\/phones\"&gt;Phones&lt;\/a&gt;\n<\/code><\/pre>\n<p>After reloading the application we should have the possibility to switch between our routes:<\/p>\n<p><a href=\"https:\/\/camo.githubusercontent.com\/e9c006e219c2f56186fb241d3112f92eed82771a\/687474703a2f2f692e696d6775722e636f6d2f54576e6838626c2e706e67\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/camo.githubusercontent.com\/e9c006e219c2f56186fb241d3112f92eed82771a\/687474703a2f2f692e696d6775722e636f6d2f54576e6838626c2e706e67\" alt=\"\" data-canonical-src=\"http:\/\/i.imgur.com\/TWnh8bl.png\" style=\"max-width:100%;\"><\/a><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>To Angular Without Preparing The Existing Code Base<\/p>\n","protected":false},"author":9,"featured_media":2997,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2429","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-unkategorisiert"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Directly Upgrading From AngularJS 1.X - ANGULARarchitects<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Directly Upgrading From AngularJS 1.X - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"To Angular Without Preparing The Existing Code Base\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2017-04-09T14:01:34+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1280\" \/>\n\t<meta property=\"og:image:height\" content=\"853\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Manfred Steyer, GDE\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daniel\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer, GDE\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/\"},\"author\":{\"name\":\"Manfred Steyer, GDE\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\"},\"headline\":\"Directly Upgrading From AngularJS 1.X\",\"datePublished\":\"2017-04-09T14:01:34+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/\"},\"wordCount\":1787,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"articleSection\":[\"Unkategorisiert\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/\",\"name\":\"Directly Upgrading From AngularJS 1.X - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"datePublished\":\"2017-04-09T14:01:34+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"width\":1280,\"height\":853},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Directly Upgrading From AngularJS 1.X\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\",\"name\":\"Manfred Steyer, GDE\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer, GDE\"},\"sameAs\":[\"https:\/\/x.com\/daniel\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Directly Upgrading From AngularJS 1.X - ANGULARarchitects","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/","og_locale":"en_US","og_type":"article","og_title":"Directly Upgrading From AngularJS 1.X - ANGULARarchitects","og_description":"To Angular Without Preparing The Existing Code Base","og_url":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/","og_site_name":"ANGULARarchitects","article_published_time":"2017-04-09T14:01:34+00:00","og_image":[{"width":1280,"height":853,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","type":"image\/jpeg"}],"author":"Manfred Steyer, GDE","twitter_card":"summary_large_image","twitter_creator":"@daniel","twitter_misc":{"Written by":"Manfred Steyer, GDE","Est. reading time":"16 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/"},"author":{"name":"Manfred Steyer, GDE","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951"},"headline":"Directly Upgrading From AngularJS 1.X","datePublished":"2017-04-09T14:01:34+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/"},"wordCount":1787,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","articleSection":["Unkategorisiert"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/","url":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/","name":"Directly Upgrading From AngularJS 1.X - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","datePublished":"2017-04-09T14:01:34+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","width":1280,"height":853},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/directly-upgrading-from-angularjs-1-x\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Directly Upgrading From AngularJS 1.X"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951","name":"Manfred Steyer, GDE","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","caption":"Manfred Steyer, GDE"},"sameAs":["https:\/\/x.com\/daniel"]}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/2429","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=2429"}],"version-history":[{"count":0,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/2429\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/2997"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=2429"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=2429"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=2429"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}