I. Version description

Original version: 2.0.0-beta.6

Target version: 4.1.1

Added scaffolding: Angular-CLI

Scaffolding version: 1.0.0-RC.1

The upgrade depends on the following versions:

"Dependencies" : {" @ presents/common ":" ^ 4.0.0 ", "@ presents/compiler" : "^ 4.0.0", "@ presents/compiler - cli" : "^ 4.0.0 @ presents/"," core ":" ^ 4.0.0 ", "@ presents/forms" : "^ 4.0.0", "@" presents/HTTP: "^ 4.0.0 @ presents/platform", "- the browser" : "^ 4.0.0", "@ presents/platform - the browser - dynamic" : "^ 4.0.0", "@ presents/router" : "^ 4.0.0 core -", "js" : "^" against 2.4.1, "RXJS" : "^ 5.1.0", "zone. Js" : "^ 0.8.4"}, "devDependencies" : {" @ presents/cli ": "1.0.0 - rc. 1", "ts - node" : "~ 2.0.0", "tslint" : "~ 4.5.0", "typescript" : "~ 2.1.0}"Copy the code

2. Dependency changes

Dependency import changes:

'Angular2 /core' => '@angular/core'' Angular2 / HTTP '=> '@angular/ HTTP' 'Angular2 /router' => '@angular/router' // form dependent 'angular2/commom' => '@angular/forms'Copy the code

3. Add NgModule

The official instructions

Angular modules help you organize your application into cohesive chunks of functionality.

Angular modules are classes with @NgModule decorator functions. The @NgModule receives a metadata object that tells Angular how to compile and run the module code. It marks the components, directives, and pipes owned by the module and exposes some of them so that external components can use them. It can add service providers to an application’s dependency injector.

Please refer to the official documentation for details.

Managing common Components

  • Create a SharedModule to manage all common components
import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {FormsModule} from '@angular/forms'; Import {SomeService} from './service/some.service'; import {SomeComponent} from './component/some.component'; import {SomePipe} from './pipe/some.pipe'; import {SomeDirective} from './directive/ng-file-select.directive'; @NgModule({ imports: [CommonModule, FormsModule], declarations: [SomeComponent, SomePipe, SomeDirective], exports: [CommonModule, FormsModule, SomeComponent, SomePipe], providers: [SomeService] }) export class SharedModule {}Copy the code
  • Other modules only need to introduce SharedModule
import {NgModule} from '@angular/core'; SharedModule import {SharedModule} from 'shared/shared.module'; Import {SomeRoutingModule} from './main-routing.module'; // Component import {SomeComponent} from './main.component'; @NgModule({ imports: [SharedModule, SomeRoutingModule], declarations: [SomeComponent], exports: [SomeComponent] }) export class SomeModule { }Copy the code

4. Route correlation

change

Split and add routing module

  • ActivatedRoute: obtains route information

  • Route event instances, such as NavigationEnd indicating that the navigation event has changed, etc

  • Anyway, a lot of changes, please check the official API documentation… [his face]

Add routing Module

Routes are created using ngModules as shown in the following example:

import {NgModule} from '@angular/core'; import {Routes, RouterModule} from '@angular/router'; import {SomeComponent} from './main.component'; import {ListComponent} from './list.component'; import {DetailComponent} from './detail.component'; Const routes: routes = [// displayName {path: '', Component: SomeComponent, data: {displayName: }, children: [{path: 'list', Component: ListComponent, data: {displayName: 'list'}}, {path: 'list', Component: DetailComponent, data: {displayName: 'detail '}}, {path: '**', redirectTo: 'list'}]},]; DetailComponent: {displayName:' detail '}}, {path: '**', redirectTo: 'list'}]},]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], providers: [] }) export class SomeRoutingModule {}Copy the code

Common Routing

// Router: router router.events.filter(event => event instanceof NavigationEnd).subscribe(event => {}); // Router: router router.events.filter(event => event instanceof NavigationEnd). // activatedRoute: activatedRoute const rootRoute: ActivatedRoute = activatedroute. root // Get root route const children: ActivatedRoute[] = rootroute. children; For (const child of children) {console.log(child.snapshot.data); // Get data console.log(child.snapshot.params); // Get params console.log(child.snapshot.url, child.snapshot.url[0].path); // Get the url or path information}Copy the code

To write about Breadcrumb functionality, refer to the Angular2 Breadcrumb using Router article.

Fifth, form related

Dependent API changes

ControlGroup => FormGroup import {ControlGroup} from 'angular2/commom'; => import {FormGroup} from '@angular/forms'; // Control => FormControl import {Control} from 'angular2/commom'; => import {FormControl} from '@angular/forms';Copy the code

The original use of the [ngFormModel] attribute

  • Change the form attribute [ngFormModel] to [formGroup]
<form [ngFormModel]="myform" /> => <form [formGroup]="myform" />
Copy the code
  • Both FormsModule and ReactiveFormsModule need to be introduced in the module file
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
Copy the code
  • Change the input attribute [ngFormControl] in the form to formControlName
<input [ngFormControl]="url" /> => <input formControlName="url" />
Copy the code
  • To add the ngFormModel property<form>Use ngModel, need to add
[ngModelOptions]="{standalone: true}" attribute <input name=" URL "[(ngModel)]="url" [ngModelOptions]="{standalone: True}" /> To use # URL ="ngForm" in <form> of the [ngFormModel] property, Need to change the verification url. Valad for mgform. Controls. Url. The valid usage ngForm changes within the form input ngControl = "url" attribute to # url = "ngModel" at the same time need to name attribute is added to the input tags <input ngControl="url" /> => <input #url="ngModel" name="url" /> If form validation is not required, do not add the name attribute, instead add [ngModelOptions]="{standalone: true}" <input #url="ngModel" /> => <input #url="ngModel" [ngModelOptions]="{standalone: <date-time-picker [(ngModel)]="start_time" /> => <date-time-picker [(ngModel)]="start_time" /> <date-time-picker name="start_time" [(ngModel)]="start_time" ngDefaultControl />Copy the code

6. Other issues

1. Background parsing errors occur when the HTTP request contains the URL

Cause: Angular (v4.0.0) fails to fetch the image address because the HTTP service standardEncoding method is shown in node_modules/@angular/ HTTP /@angular/http.js. Solution: Use encodeURIComponent to override standardEncoding

/** * override the original standardEncoding method, see http.js */ class MyQueryEncoder extends QueryEncoder {encodeKey(k: string): string { return encodeURIComponent(k); } encodeValue(v: string): string { return encodeURIComponent(v); }}Copy the code

2. Failed to subscribe to events after component migration

Reason: Angular (V4.0.0) creates different instances of dependency injection if you declare providers in different places.

Solution: Declare the Provider in the app root component to inject the ResultHandler service, so that the entire app uses the same instance.

3. Upgrade angular-CLI failed

Cause: After the angular-CLI version is upgraded, the default disableHostCheck attribute of the corresponding WebPack version is changed, causing Invalid Host header to appear in ng serve –port. Workaround: roll back the version or manually change the webpack configuration in node_modules (see nvalid Host header after updating to 1.0.1 #6070).

4. The NPM run build –prod command fails to run

The reason: basically the problem is in AOT and Angular analyzer. It analyzes code in all cases whether you wanted to have aot or not. -prod => –prod –aot=false 2) -prod => –env=prod (ng build-prod Module not found: Error: Can’t resolve ‘./? _gendir/app/app. The module. Ngfactory ‘# 4551)

PS: Running code can be dynamically booted by a just-in-time JIT compiler or by using aoT-ahead-of-time. Static boot. Static solutions generate smaller, faster startup applications and are preferred by default. But here because some dynamic computing environment code, so failed to compile, here manually closed.

5. After you upgrade Angular (v2.4.0) to (V4.1.1), the status in the left navigation fails

Cause: After the upgrade, the router and Component hook order was adjusted (based on personal observation, not verified) so that the component state was not updated at the end of the routing event. Workaround: The component state is currently manually updated at the end of the routing event.

The inline style is invalid. “> < div style=”color: {{someValidation? The inline style of ‘red’ : ‘}}” is invalid.

Reason: In Angular (V4.1.1), styles are set using the [ngStyle] property. [ngStyle]=”{‘color’: someValidation? [style. Color]=”someValidation?” ‘red’ : ‘ ‘”.

7. In WebStorm, changing files does not update output in the browser.

Cause: “Safe Write” is enabled in WebStorm by default, which saves to temporary files first. Solution: Close File > Settings… > System Settings > Use “safe write”, see angular-cli issue#5507.

Failed to obtain RouteParams API from router.

Cause: Angular (V4.1.1) uses the ActivatedRoute API to obtain routing information.

The original code:

import { RouteParams } from 'angular2/router'; . // ngOnInit() {this.id = parseInt(this._routeparams.get ('id')); this.needSaveBtn = (this._routeParams.get('action') || '') ! = 'detail'; // View, edit, add... // Other code}... // Rest of the codeCopy the code

The new code:

import { ActivatedRoute } from '@angular/router'; . {this._route.params.subscribe ((params) => {this.id = parseInt(params['id']); this.needSaveBtn = (params['action'] || '') ! = 'detail'; // View, edit, add... }); }... // Rest of the codeCopy the code

9. Unable to customize the webpack alias using Angular-CLI, resulting in long file import paths, such as.. /.. /.. / Shared /.

Cause: Angular – CLI encapsulates webpack configuration, so manually changing node_modules is inconvenient. Fix (build): Use baseUrl and Paths from tsconfig #2470.

Usage:

Json {"compilerOptions": {... / / add path related "baseUrl" : ""," paths ": {" @ Shared / *" : [" app/Shared / * "]}... },... } // Modify tsconfig.json in the root directory // mainly for compiler IDE detection using {"compilerOptions": {... / / add path related "baseUrl" : ""," paths ": {" @ Shared / *" : [" SRC/app/Shared / * "]}... },... }Copy the code

10. Component migration status updates fail after upgrading Angular (V4.1.1)

Cause: After the upgrade, the component hook order was adjusted so that the component state could not be updated after the Component state update.

Solution: When detecting status changes, manually add status updates.

11. After upgrading Angular to v4.1.1,<iframe>Error is raised with attributes such as dynamic SRC

Cause: Angular2 enables security innocency. To prevent XSS attacks, refer to the official document security.

Solution: Inject DomSanitizer to mark a value as trusted by adding a pipe component called safeUrl, located at app/shared/pipe/safe-url.main.pipe.ts. Method of use: < iframe/SRC = “url | safeUrl” >

12. Failed to start app after migrating some files, Cannot read property ‘length’ of undefined

Cause: Some files contain ///, if the path is not correct, the file cannot be started.

Solution: Adjust the file path, or delete these contents.