Build Errors
一般的な間違い
デコレーターにて丸括弧を忘れる
デコレーターはアノテーションの後に丸括弧 ()
を持つべきです。いくつか例を示します: @Injectable()
, @Optional()
, @Input()
, など。
@Directive({
selector: 'my-dir',
})
class MyDirective {
// 誤り、@Optional() とすべき
// @Optional はここでは何もしないため、MyDirective は parent が undefined の場合にエラーになる
constructor(@Optional parent: ParentComponent) {}
}
一般的なエラー
すべてのパラメータを解決できない
Cannot resolve all parameters for 'YourClass'(?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'YourClass' is decorated with Injectable.
この例外は Angular が YourClass
のコンストラクタの 1 つ以上のパラメータについて困惑していることを意味します。依存性を注入 するため、Angular は 注入するパラメータの型を知る必要があります。パラメータのクラスを指定することで Angular にこのこと(タイプ)を知らせます。次の点を確認してください:
- パラメータのクラスをインポートします。
- パラメータに適切な注釈をつけるか、パラメータの型を指定します。
import { MyService } from 'my-service'; // 私をインポートすることを忘れないで!
@Component({
template: `Hello World`,
})
export class MyClass {
// service は MyService のタイプです
constructor(service: MyService) {}
}
コード内の循環参照がこのエラーの原因になることがあります。循環参照は、2 つのオブジェクトが相互に依存していることを意味するため、両方を相互の前に宣言する方法はありません。この問題を回避するには、Angular に組み込まれているforwardRef
関数を使用します。
import { forwardRef } from '@angular/core';
@Component({
selector: 'my-button',
template: `<div>
<icon></icon>
<input type="button" />
</div>`,
directives: [forwardRef(() => MyIcon)], // MyIcon はまだ定義されていません
}) // forwardRef は MyIcon が必要なときに MyIcon として解決します
class MyButton {
constructor() {}
}
@Directive({
selector: 'icon',
})
class MyIcon {
constructor(containerButton: MyButton) {} // MyButton が定義されました
}
No provider for ParamType
No provider for ParamType! (MyClass -> ParamType)
これは、Angular は注入されるべきパラメータの型を知っているが、注入方法を知らないことを意味する。
パラメータが Service の場合は、指定したクラスがアプリケーションで使用可能な providers のリストに追加されていることを確認します:
import { MyService } from 'my-service';
@Component({
templateUrl: 'app/app.html',
providers: [MyService], // 私を忘れないで!
})
class MyApp {}
パラメータが別のコンポーネントまたは Directive(たとえば、親コンポーネント)である場合、パラメータを providers のリストに追加するとエラーはなくなりますが、これは前述の provider の複数のインスタンス と同じ効果を持ちます。ここでは、コンポーネントクラスの新しいインスタンスを作成しますが、必要なコンポーネントインスタンスへの参照は取得しません。かわりに、注入されるであろう Directive またはコンポーネントがコンポーネントで使用可能であることを確認します(たとえば、親であることを期待している場合は、実際に親であること)。これはおそらく、例を使用すると最も簡単に理解できます:
@Component({
selector: 'my-comp',
template: '<p my-dir></p>',
directives: [forwardRef(() => MyDir)],
})
class MyComp {
constructor() {
this.name = 'My Component';
}
}
@Directive({
selector: '[my-dir]',
})
class MyDir {
constructor(c: MyComp) {
// <-- This is the line of interest
// コンポーネントツリーにMyCompがなく、注入するMyCompがないため、
// Directiveが通常のdivにある場合のエラーのdivにある場合のエラー
console.log("Host component's name: " + c.name);
}
}
@Component({
template:
'<my-comp></my-comp>' + // MyDir コンストラクタ内ではエラーなし、MyComp は MyDir の親
'<my-comp my-dir></my-comp>' + // MyDir コンストラクタ内ではエラーなし、MyComp は MyDir のホスト
'<div my-dir></div>', // MyDir コンストラクタ内でエラー
directives: [MyComp, MyDir],
})
class MyApp {}
以下に、使用可能な注入するものの図を示します:
+-------+
| App |
+---+---+
|
+-------------+------------+
| |
+------+------+ +--------+--------+
| Div (MyDir) | | MyComp (MyDir) | <- MyComp は注入可能
+-------------+ +--------+--------+
^ |
MyComp の注入なし +------+------+
| P (MyDir) | <- MyComp は親から注入可能
+-------------+
前の例を拡張するために、コンポーネント/Directive の参照を常に期待しているわけではない場合には、Angular の @Option
アノテーションを使うことができます:
@Directive({
selector: '[my-dir]',
})
class MyDir {
constructor(@Optional() c: MyComp) {
// No longer errors if c is undefined
if (c) {
console.log(`Host component's name: ${c.name}`);
}
}
}