今回は、「Routing」です。すみません、今回はハマった部分だけ掲載しているので、チュートリアルは、Angular Docs を見ながら進めてもらえればと思います。
まずは、AngularJSの開発用サーバーを起動しておきます。
cd C:¥workspace¥firstSpring¥src¥main¥resources¥static¥angular-tour-of-heroes npm start
AngularJSはコード記述のルールが結構...
ちょっと、脱線してしまうんですが、チュートリアル通りやっててエラーが出て、調べてたら、
・typescript - TSLint: Too many spaces before 'from' (import-spacing) - Stack Overflow
⇧ 上記サイトに辿り着き、なんか「tslint.json」ファイルの設定を変えたら良いよ的な発言がなされていました。「Jump to rule configulation」を選択すると、「tslint.json」ファイルにとべます。
ややこしいのが、「パッケージ・エクスプローラー」に表示されない、「C:¥workspace¥firstSpring¥target¥classes¥static¥angular-tour-of-heroes¥tslint.json」にとぶってことです。
「パッケージ・エクスプローラー」に表示されている「C:¥workspace¥firstSpring¥src¥main¥resources¥static¥angular-tour-of-heroes¥tslint.json」を編集するんじゃないみたいです。
⇧ ここの「tslint.json」ファイルを編集する必要があるっぽいです。
その前に、ホワッツ ? 「tslint.json」って何ですか?確かに、AngularJSのプロジェクトフォルダ直下(「angular-tour-of-heroes」>「tslint.json」)に、そんなファイルがありますが...。
TSLint
TSLint is an extensible static analysis tool that checks TypeScript code for readability, maintainability, and functionality errors. It is widely supported across modern editors & build systems and can be customized with your own lint rules, configurations, and formatters.
TSLint supports:
- custom lint rules
- custom formatters (failure reporters)
- inline disabling and enabling of rules with comment flags
- configuration presets (
tslint:latest
,tslint-react
, etc.) and plugin composition - automatic fixing of formatting & style violations
- integration with MSBuild, Grunt, Gulp, Atom, Eclipse, Emacs, Sublime, Vim, Visual Studio 2015, Visual Studio 2017 Visual Studio code, WebStorm and more
GitHub - palantir/tslint: An extensible linter for the TypeScript language
TypeScriptの「静的解析ツール」らしいですね。ファイルの実行前に、コード上でエラーなどを知らせてくれるもんみたいですね。Javaでいうところの「FindBug」的なものですかね?
lintは、「C言語」発祥ですかね?
lint とは、主にC言語のソースコードに対し、コンパイラより詳細かつ厳密なチェックを行うプログラムである。コンパイラではチェックされないが、バグの原因になるような曖昧な記述についても警告される。
転じて、C言語に限らず、各種言語で書かれた文書に対して文法チェックを行うプログラムも、lint と呼ばれるようになった。この意味での lint の代表例としては、 HTML の文法チェックを行う Another HTML-lint がある。
ということで、「ESLint」「scss-lint」「sass-lint」「CSS LINT」「haml-lint」など様々なlintが存在するようです。
・JavaScript/CSSのLint系ライブラリまとめ | hifive開発者ブログ
で、「TSLint」の検証のルールを定義をしているファイルが「tslint.json」ということになるらしいです。
Angular CLI(「@angular/cli」)でAngularJSのプロジェクトを作成したときにデフォルトで「tslint.json」作成されるっぽいです。
・【tslint】@angular/cliでng newした時のtslint.jsonの中身についてざっくりと - Qiita
・GitHub - mgechev/codelyzer: Static analysis for Angular projects.
で、途中で「C:¥workspace¥firstSpring¥target¥classes¥static¥angular-tour-of-heroes¥tslint.json」を編集することになります。(もしかしたら、編集しなくてもいけるのかもしれませんが自分はエラーが消えなかったので...)
なので、今回は(毎回ですが)かなり間違ってる可能性があるので、ここから先は、お時間のある方のみご覧ください。
Routingのチュートリアル
「app.component.ts」の内容が、「Heroes」 専用になってしまっているので、「app.component.ts」をリネームして「heroes.component.ts」に名前を変えるようです。
「app.component.ts」を選択した状態で右クリックし、「リファクタリング(T)」>「名前変更(M)...」をクリック。
「新しい名前(M):」を「heroes.component.ts」とし、「OK」。
そのあと、「heroes.component.ts」を編集。「selector」「class」名を変えれば良いらしい。
import { Component, OnInit } from '@angular/core'; import { Hero } from './hero'; import { HeroService } from './hero.service'; @Component({ selector: 'my-heroes', template: ` <h1>{{title}}</h1> <h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> </ul> <hero-detail [hero]="selectedHero"></hero-detail> `, styles: [` .selected { background-color: #CFD8DC !important; color: white; } .heroes { margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 15em; } .heroes li { cursor: pointer; position: relative; left: 0; background-color: #EEE; margin: .5em; padding: .3em 0; height: 1.6em; border-radius: 4px; } .heroes li.selected:hover { background-color: #BBD8DC !important; color: white; } .heroes li:hover { color: #607D8B; background-color: #DDD; left: .1em; } .heroes .text { position: relative; top: -3px; } .heroes .badge { display: inline-block; font-size: small; color: white; padding: 0.8em 0.7em 0 0.7em; background-color: #607D8B; line-height: 1em; position: relative; left: -1px; top: -4px; height: 1.8em; margin-right: .8em; border-radius: 4px 0 0 4px; } `], providers: [HeroService] }) export class HeroesComponent implements OnInit { title = 'Tour of Heroes'; heroes: Hero[]; selectedHero: Hero; constructor(private heroService: HeroService) { } getHeroes(): void { this.heroService.getHeroes().then(heroes => this.heroes = heroes); } ngOnInit(): void { this.getHeroes(); } onSelect(hero: Hero): void { this.selectedHero = hero; } }
保存で、はい、エラー!
・GitHub - mgechev/codelyzer: Static analysis for Angular projects.
⇧ この方たちの話が正しいのだとすると、
Below you can find a recommended configuration which is based on the Angular Style Guide.
{ // The rule have the following arguments: // [ENABLED, "attribute" | "element", "selectorPrefix" | ["listOfPrefixes"], "camelCase" | "kebab-case"] "directive-selector": [true, "attribute", ["dir-prefix1", "dir-prefix2"], "camelCase"], "component-selector": [true, "element", ["cmp-prefix1", "cmp-prefix2"], "kebab-case"], "use-input-property-decorator": true, "use-output-property-decorator": true, "use-host-property-decorator": true, "no-attribute-parameter-decorator": true, "no-input-rename": true, "no-output-rename": true, "no-forward-ref": true, "use-life-cycle-interface": true, "use-pipe-transform-interface": true, // [ENABLED, "SUFFIX"] // Where "SUFFIX" is your custom suffix, for instance "Page" for Ionic 2 components. "component-class-suffix": [true, "Component"], "directive-class-suffix": [true, "Directive"], "templates-use-public": true, "no-access-missing-member": true, "invoke-injectable": true }
まじか...自分で「selector」を追加しないといけないらしい、「selector」増えるたびに手動で追加?その作りってどうなの?って思ってしまったのは自分だけ?
「問題」の該当する項目をダブルクリックすると問題の個所にとべます。
赤い波線の部分にカーソルを持っていくと、選択肢が出てくるので、「Jump to configuration of rule 'component-selector'」を選択。
ファイルが開かれるので、編集します。後で出てくる「my-dashboard」「my-hero」とかの「selector」の設定もしておきます。
{ "rulesDirectory": [ "node_modules/codelyzer" ], "rules": { "arrow-return-shorthand": true, "callable-types": true, "class-name": true, "comment-format": [ true, "check-space" ], "curly": true, "eofline": true, "forin": true, "import-blacklist": [ true, "rxjs" ], "import-spacing": false, "indent": [ true, "spaces" ], "interface-over-type-literal": true, "label-position": true, "max-line-length": [ true, 140 ], "member-access": false, "member-ordering": [ true, { "order": [ "static-field", "instance-field", "static-method", "instance-method" ] } ], "no-arg": true, "no-bitwise": true, "no-console": [ true, "debug", "info", "time", "timeEnd", "trace" ], "no-construct": true, "no-debugger": true, "no-duplicate-super": true, "no-empty": false, "no-empty-interface": true, "no-eval": true, "no-inferrable-types": [ true, "ignore-params" ], "no-misused-new": true, "no-non-null-assertion": true, "no-shadowed-variable": true, "no-string-literal": false, "no-string-throw": true, "no-switch-case-fall-through": true, "no-trailing-whitespace": true, "no-unnecessary-initializer": true, "no-unused-expression": true, "no-use-before-declare": true, "no-var-keyword": true, "object-literal-sort-keys": false, "one-line": [ true, "check-open-brace", "check-catch", "check-else", "check-whitespace" ], "prefer-const": true, "quotemark": [ true, "single" ], "radix": true, "semicolon": [ true, "always" ], "triple-equals": [ true, "allow-null-check" ], "typedef-whitespace": [ true, { "call-signature": "nospace", "index-signature": "nospace", "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" } ], "typeof-compare": true, "unified-signatures": true, "variable-name": false, "whitespace": [ true, "check-branch", "check-decl", "check-operator", "check-separator", "check-type" ], "directive-selector": [ true, "attribute", ["app", "my*", "hero*"], "camelCase" ], "component-selector": [ true, "element", ["app", "my*", "hero*"], "kebab-case" ], "use-input-property-decorator": true, "use-output-property-decorator": true, "use-host-property-decorator": true, "no-input-rename": true, "no-output-rename": true, "use-life-cycle-interface": true, "use-pipe-transform-interface": true, "component-class-suffix": true, "directive-class-suffix": true, "no-access-missing-member": true, "templates-use-public": true, "invoke-injectable": true } }
もしかしら、Eclipseだから起きる不具合なのかな?ネットでみんなこの問題に触れてないっぽいんですよね、Eclipse以外(Visual Studioとか)では自動で解決してくれるんですかね?
モヤモヤしますが、他の部分に関しては、チュートリアル通りに進めていくことができるはずです。チュートリアルを完成させて、「http://localhost:4200」にアクセスすると、
ページが表示され、「Narco」をクリックすると、詳細が表示されます。
「Heroes」は一覧ですね。ここから選択した人の詳細も「View Details」からいけるようです。
エラーが更新されないときは、コマンドプロンプトで動かしているAngularJSの開発用サーバーを「Ctrl + C」で一旦止めてから、「npm start」で再度、起動すると動くかもです。(「npm start」で起動すると、ファイルの更新が即反映されるはずなんですが、自分は何回かサーバー再起動しました、モヤっとしますね。)
・FN1706006 | Angular 4入門 06: Routerを使う | HTML5 : テクニカルノー
・Angular2 The Tour of Heroes tutorial に挑戦してみる 5 - Djangoroidの奮闘記
ちょっと今回は、まとめられなくてすみません。上記サイトが詳しく解説してくださってます。
今回はハマった部分だけの掲載とさせていただきました。
Angular Docs の live example / download example でダウンロードしたファイルの「tslint.json」ファイルには、
"directive-selector": [ true, "attribute", "app", "camelCase" ], "component-selector": [ true, "element", "app", "kebab-case" ]
の部分が無いんですよね。設定ファイルのところとかもチュートリアルに載せてくれたら良いんですけどね...。(英語だから、自分が見落としてる可能性大ですが。)
「tslint.json」が2つ存在する理由も分からずです。
そして、「Routing」機能。ページ遷移って、普通に<a>タグのhref属性じゃだめなのかな?と思ってしまいましたが、何かきっとメリットがあるんでしょうね、早くそういうことが分かるレベルまで行きたいものですね。
今回も盛大にハマって時間が...調べる時間を短縮していきたいもんです(涙)。