У меня есть сценарий использования для переноса большого приложения angularjs, и я хочу начать с этого процесса вначале в небольшом приложении. По этой причине я ознакомился с веб-приложением heroes angularjs и начал добавлять в него angular (создав новый проект с angular-cli), а затем добавив модуль NgUpgrade.
Проблема, с которой я столкнулся сейчас, заключается в том, что веб-приложение angularjs довольно хорошо работает внутри приложения angular 8, но компоненты, принадлежащие angular 8, не отображаются.
У меня такое впечатление, что мои угловые компоненты не загружаются, так как я загрузил вручную angularjs, но я не уверен ... когда я явно добавляю свойство bootstrap в @NgModules, оно работает только для угловыхкомпоненты, но не для angularjs (это имеет смысл). Поэтому я подумал, может быть, мне нужно обновить компоненты angularjs или понизить версию новейших угловых компонентов, но я так не думаю.
Здесь вы найдете репозиторий git с кодом. Ниже больше информации, связанной с моим проектом:
- угловая версия: 8.2.8
- angularJS версия: 1.6.10
- angular-cli: 8.3.6
Структура проекта
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Common</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<hero-list></hero-list>
</body>
</html>
index.ts (корневой модуль angularjs)
// initialize root module and make it exportable to be able to bootstrap it
// inside angular
export const heroAppModule = angular.module('heroApp', [
'ngMaterial',
'perfect_scrollbar',
'ngJsTree',
'ngTagsInput',
'ui.router',
'heroApp.underscore'
]).config(['$stateProvider', function ($stateProvider) {
var heroState = {
name: 'hero',
url: '/hero',
template: '<hero-list></hero-list>'
};
$stateProvider.state(heroState);
}]);
/** start: REQUIRE ZONE for angularjs
* Add angularjs files since they aren't yet fully ES6 modules
* we use requirejs as module loader
*/
require('./editable-field/editable-field');
require('./hero-detail/hero-detail');
require('./hero-list/hero-list');
require('./underscore/underscore.module');
require('./underscore/underscore.service');
/**
* end: REQUIRE ZONE for angularjs
*/
app.module.ts (загрузка angularjs с помощью NgUpgrade)
import * as angular from 'angular';
import { UpgradeModule, setAngularJSGlobal } from '@angular/upgrade/static';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { heroAppModule } from './../ngjs/index';
import { HelloworldComponent } from './helloworld/helloworld.component';
@NgModule({
declarations: [ HelloworldComponent ],
imports: [
BrowserModule,
UpgradeModule
] // ,
// bootstrap: [HelloworldComponent]
})
export class AppModule {
constructor(private upgrade: UpgradeModule) { }
ngDoBootstrap() {
setAngularJSGlobal(angular);
this.upgrade.bootstrap(document.body, [heroAppModule.name], { strictDi: true });
}
}
main.ts
import 'zone.js/dist/zone'; // Included with Angular CLI.
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/ngx/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
компонент списка героев (angularjs)
declare var angular: angular.IAngularStatic;
(function () {
'use strict';
angular.module('heroApp').component('heroList', {
template: require('html-loader!./hero-list.html'),
controller: HeroListController,
controllerAs: 'vm'
});
HeroListController.$inject = ['$scope', '$element', '$attrs'];
function HeroListController($scope, $element, $attrs) {
var vm = this;
vm.list = [
{
name: 'Superman',
location: 'The sky'
},
{
name: 'Batman',
location: 'Baticueva'
}
];
vm.updateHero = function (hero, prop, value) {
hero[prop] = value;
};
vm.deleteHero = function (hero) {
var idx = vm.list.indexOf(hero);
if (idx >= 0) {
vm.list.splice(idx, 1);
}
};
}
})();
компонент app-root (имя файла: helloworld.component)
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './helloworld.component.html',
styleUrls: ['./helloworld.component.scss']
})
export class HelloworldComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
шаблон приложения-root
<p>helloworld works!</p>
angular.json (файл angular-cli)
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"common": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/common",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"assets": [
"src/favicon.ico",
"src/assets" ],
"styles": [
"bower_components/jstree/dist/themes/default/style.min.css",
"bower_components/ng-tags-input/ng-tags-input.bootstrap.min.css",
"bower_components/utatti-perfect-scrollbar/css/perfect-scrollbar.css",
"bower_components/angular-material/angular-material.css",
"src/styles.scss"
],
"scripts": [
"bower_components/jquery/dist/jquery.js",
"bower_components/angular/angular.js",
"bower_components/angular-material/angular-material.js",
"bower_components/angular-animate/angular-animate.js",
"bower_components/angular-aria/angular-aria.js",
"bower_components/jstree/dist/jstree.js",
"bower_components/ng-js-tree/dist/ngJsTree.js",
"bower_components/ng-tags-input/ng-tags-input.js",
"bower_components/utatti-perfect-scrollbar/dist/perfect-scrollbar.js",
"bower_components/angular-perfect-scrollbar/src/angular-perfect-scrollbar.js",
"node_modules/@uirouter/angularjs/release/angular-ui-router.min.js",
"node_modules/underscore/underscore.js"
]
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "common:build"
},
"configurations": {
"production": {
"browserTarget": "common:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "common:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "common:serve"
},
"configurations": {
"production": {
"devServerTarget": "common:serve:production"
}
}
}
}
}},
"defaultProject": "common"
}
Результат ...