[]
Wijmo Angular コンポーネント により、AngularテンプレートマークアップでWijmo コントロール を使用できるようになります。TypeScriptクラス継承機能の用語で言えば、Wijmo Angular コンポーネント は、それらが表す コントロール クラスを「拡張」しています。すなわち、Wijmoコンポーネントへの参照を取得した場合、参照されるインスタンスは、コンポーネントのすべてのプロパティ、イベント、メソッドを含むWijmo コントロール であると同時に、Angular コンポーネント でもあります。Wijmoコンポーネントは、コントロールクラスを拡張し、Angularテンプレートマークアップでコントロールを使用できるようにするために必要な機能を追加し、完全に機能する一方向/双方向のプロパティ連結およびイベント連結を備えています。Wijmoコントロール、Wijmo Angularコンポーネント、そしてAngular自体がすべて同じTypeScript言語で記述されているため、この統合はスムーズです。
Wijmo Angularコンポーネントは、コアライブラリパッケージごとに1つのnpmパッケージのセットとして出荷され、名前には「angular2」という単語が含まれています。たとえば、"wijmo.angular2.grid"パッケージは、コアの"wijmo.grid"パッケージのコントロールのコンポーネントを表します。パッケージは別々にインストールすることも、"@mescius/wijmo.angular2.all"グループパッケージを使ってまとめてインストールすることもできます。
npm install @mescius/wijmo.angular2.all
Wijmo npmパッケージの詳細については、「npmによるWijmoの参照」トピックを参照してください。
その後、ESMの_import_ステートメントを使用してモジュールをインポートできます。たとえば、次のimport文は"wijmo.angular2.grid"モジュールの内容をインポートします。
import * as wjGrid from '@mescius/wijmo.angular2.grid';
Angular CLIを使用してアプリケーションを作成する方法については、「Angular & Wijmoクイックスタート」ブログを参照してください。
この設定により、Wijmo Angularモジュールをインポートし、モジュールに含まれるコンポーネントやディレクティブを使用できます。たとえば、次のコードは、MyCmpコンポーネントのテンプレートにWjFlexGridコンポーネントを追加し、追加したグリッドへの参照をflexプロパティに設定します。
import { Component, ViewChild } from '@angular/core';
import { WjGridModule, WjFlexGrid } from '@mescius/wijmo.angular2.grid';
@Component({
template: '<wj-flex-grid #flex [itemsSource]="data"></wj-flex-grid>',
selector: 'my-cmp',
imports: [WjGridModule,WjFlexGrid],
standalone: true
})
export class MyCmp {
data: any[];
@ViewChild('flex') flex: WjFlexGrid;
}
以前は、Wijmoコンポーネントを組み込むには NgModules を使用する必要があり、追加の定型コードが必要でした。
現在は、スタンドアロンコンポーネントを使用して、必要なWijmoモジュールをコンポーネント デコレータに直接インポートできるため、NgModules は不要です。
WijmoのFlexGridをAngularのスタンドアロンコンポーネントとして使用する場合は、@mescius/wijmo.angular2.grid からWjGridModuleとWjFlexGridをインポートする必要があります。さらに、必要に応じて他の Angular coreモジュールもインポートしてください。
Wijmoコントロールを正常に表示および動作させるには、Wijmo CSSファイルをアプリケーションにロードする必要があります。
スタイルは @mescius/wijmo.styles npmパッケージに含まれます。主要なCSSファイルは2つあります。
wijmo.css:すべてのWijmoコントロールのスタイルが含まれます。
wijmo-core.css:wijmo.cssの縮小版で、Enterprise専用コントロールのスタイルは含まれません。
好みに応じて、Angular CLIアプリケーションの次のいずれかの場所でスタイルをロードできます。
このimportステートメントをファイルの先頭に追加するだけです。
@import '@mescius/wijmo.styles/wijmo.css';
wijmo.cssファイルへのパスを、アプリケーションで使用される他のcssファイルとともに、projects.architect.build.options.stylesフィールドに追加します。
"styles": [
"node_modules/@mescius/wijmo.styles/wijmo.css",
"src/styles.css"
],
ここでは、CSSファイルへの相対パスを_node_modules_ フォルダーを含めて指定する必要があることに注意してください。styles配列のアプリケーションCSSファイルの前にwijmo.cssファイルを追加することをお勧めします。これにより、WijmoコンポーネントをカスタマイズするCSSルールが正しく適用されます。
Angular用のWijmo コンポーネント は、テンプレートマークアップで使用されます。コードでWijmoコントロールを作成する場合は、コンポーネントではなく、その目的で用意されているコアモジュールのWijmo コントロール を使用する必要があります。コアモジュールの名前は、対応するAngular相互運用モジュール名から「angular2」を省略した名前と同じです。たとえば、次のコードは、コードでFlexGridコントロールを作成します。
import { FlexGrid } from '@mescius/wijmo.grid';
let flex = new FlexGrid('#host_element');
WjFlexGrid コンポーネントの代わりに FlexGrid コントロールをインポートして、「@mescius/wijmo.angular2.grid」モジュールの代わりに「@mescius/wijmo.grid」モジュールからインポートしていることに注意してください。
Wijmo Angularコンポーネントは、テンプレートマークアップでコンポーネントを指定するために、一貫した命名規則を使用します。コンポーネントに使用されるHTML要素名と属性名は、以下の単純なルールを使用しており、コンポーネントクラスやメンバ名から容易に推測できます。
Wijmoコンポーネントを表すHTML要素名は、小文字ハイフン構文を使用して指定されます。たとえば、WjInputNumberコンポーネントは、wj-input-numberになります。
<wj-input-number [(value)]="amount"></wj-input-number>
Wijmo属性ディレクティブには、キャメルケース形式のクラス名が使用されます。つまり、最初の文字が小文字のクラス名になります。たとえば、WjFlexGridCellTemplateディレクティブは、wjFlexGridCellTemplate属性を使用して定義されます。
<template wjFlexGridCellTemplate [cellType]="'Cell'"></template>
Wijmoコンポーネントのプロパティおよびイベントを表す属性の名前は、コンポーネントクラスインタフェースから公開されているプロパティおよびイベントの名前と正確に同じです。プロパティ名は、一方向連結の場合は角かっこで囲み(**[isReadOnly]など)、双方向連結の場合は角かっことかっこで囲みます([(value)]など)。イベント名は、かっこで囲みます((valueChanged)**など)。次に例を示します。
<wj-input-number
[(value)]="amount" // two-way binding to a component property
[format]="'n0'" // one-way binding to string
[isReadOnly]="true" // one-way binding to boolean
(valueChanged)="valueChanged($event)"> // event binding
</wj-input-number>
連結式は、代入先のプロパティタイプと同じ型の値として評価されます。上の例のformat文字列型プロパティには、文字列リテラルを表す一重引用符で囲まれたn0が代入されています。引用符を省略して単にn0を指定した場合、この式はプロパティ名として処理されます。同様に、isReadOnlyブール値プロパティはtrueに連結されていますが、引用符はありません。trueはブール値型の定数であり、一重引用符で囲まれた 'true' は文字列リテラルを表すからです。
Wijmoイベントハンドラは、送信元とイベント引数の2つのパラメータを持つ関数として定義されます。AngularのEventEmitter実装は、イベントイニシエータからサブスクライバに1つだけパラメータを渡すことができ、これには、テンプレートマークアップの**$event**ローカル変数の値としてアクセスできます。Wijmoイベントは、このパラメータにイベント引数を渡します。次に例を示します。
<wj-flex-grid
[itemsSource]="data"
(deletingRow)="beforeDelete($event)"> // $event contains CellRangeEventArgs object here
</wj-flex-grid>
TypeScript/JavaScriptコードでWijmoコントロールイベントをサブスクライブするときのように、イベントハンドラで送信元も受け取る場合は、コンポーネントにローカルテンプレート変数を追加し、それをイベント引数と共にイベントハンドラに渡すだけです。
<wj-flex-grid #flex // 'flex' local variable references the grid component instance
[itemsSource]="data"
(deletingRow)="beforeDelete(flex, $event)"> // pass sender ('flex') and event arguments ($event) to the handler
</wj-flex-grid>
すべてのWijmo Angularコンポーネントには、コントロールがページに追加されて初期化された後に発生する「initialized」イベントがあります。
このイベントを使用して、マークアップでプロパティを設定するほかに、追加的な初期化を実行できます。次に例を示します。
<wj-flex-grid #flex (initialized)="initGrid(flex)">
</wj-flex-grid>
// implementation
export class AppComponent {
constructor() {
this.data = ...;
}
// add custom merge manager to the FlexGrid
initGrid(flex) {
flex.mergeManager = new CustomMerge(flex);
}
}
Angular 8以前では、プロパティの初期化順序はWijmoコンポーネントの内部で定義されていたため、コンポーネント要素で指定されたプロパティの割り当て順序とは関係なく、常に同じ正しい順序で初期化されます。技術的には、初期化の順序は、@Componentデコレータのinputsプロパティのプロパティ名の順序によって決まります。
Angular 9では状況が変わり、デフォルトでこのフレームワークで使用される新しいIvyコンパイラーが登場しました。Ivyでは、開発者が要素に指定した順序でプロパティが初期化されます。したがって、Angular 9以降では、正しいプロパティ初期化順序を指定することは、コンポーネントを使用する開発者の責任です。
例として、このマークアップを考えてみましょう。
<wj-list-box [selectedIndex]="3" [itemsSource]="data"></wj-list-box>
Angular 8以前では正しく動作し、リストは4番目のアイテムが選択された状態で表示されます。Angular 9以降では結果が異なり、リストは最初の項目が選択された状態で表示され、selectedIndexプロパティへの割り当ては無視されます。
これは次のような理由で発生します。selectedIndexがitemsSourceの前に定義されると、コントロールがitemsSourceプロパティを介してその項目配列を受け取る前にselectedIndexが割り当てられますが、この時点ではインデックス3の項目はありません。
Angular 8以前では、初期化順序はコンポーネントによって内部的に定義されていたため、selectedIndexは常にitemsSourceの 後 に割り当てられます。
これを修正し、このマークアップをAngularのすべてのバージョンで期待どおりに機能させるには、selectedIndexをitemsSourceの 後 で定義する必要があります。
<wj-list-box [itemsSource]="data" [selectedIndex]="3"></wj-list-box>
もう1つの例として、isRequiredプロパティをfalseに設定した場合を考えてみましょう。この設定を行うと、コンポーネントの値にnull値を設定することができます。
次のマークアップは、Angular 9以降で例外を発生させます(ただし、Angular 8では正常に機能します)。
<wj-input-number [value]="null" [isRequired]="false"></wj-input-number>
これは、isRequiredがfalseに設定される前に、null値の割り当てが試行されるためです。
正しい定義は次のようになります。
<wj-input-number [isRequired]="false" [value]="null"></wj-input-number>
これはすべてのAngularバージョンで機能します。
なお、プロパティの正しい初期化順については、コンポーネントメタデータのinputsの順を確認しその順番に沿って指定することができます。
例として、WjInputNumberの場合はwjInputNumberMetaのinputsを参照し、その順でプロパティを設定してください。
//wjInputNumberMetaをインポートして下さい。
import { wjInputNumberMeta } from '@mescius/wijmo.angular2.input';
export class AppComponent {
constructor() {
//確認する方法はコンソール出力でなくても問題ありません。
console.log(wjInputNumberMeta.inputs)
}
}
Ivyコンパイラーが有効な時、Wijmoコンポーネントを継承したい場合は以下のような注意点が必要になります。
注意点①:Componentのtemplateは明示的に指定する必要があります。
@Component({
selector: 'app-custom-input-number',
// テンプレートは明示的に指定する必要があります。
// 単純なコンポーネントの場合は ''、子コンテンツが含まれる可能性のあるコンポーネントの場合は '<div> <ng-content> </ ng-content> </ div>'を指定します。
// また、WjTabとWjAccordionPaneの場合は、'<ng-content></ng-content>'を指定してください。
template: '',
注意点②:Componentのinputs、outputsは継承元クラスから継承されますので指定する必要はありません。継承元クラスのメタデータを指定すると、下記のエラーが発生します。
error NG1010: Failed to resolve @Directive.inputs to a string array
また、継承先コンポーネントで新たに追加されたプロパティやイベントを定義する場合は、下記のようなコードで指定できます。
@Component({
selector: 'app-custom-input-number',
・・・途中省略・・・
inputs: ['newProperty'],
outputs: ['newEvent'],
注意点③:Componentのprovidersでは、継承先コンポーネントに関する情報と、継承元クラスのメタデータから取得した継承元クラスのprovidersを取得する必要があります。
@Component({
selector: 'app-custom-input-number',
・・・途中省略・・・
providers: [
{ provide: 'WjComponent', useExisting: forwardRef(() => CustomInputNumberComponent) },
...wjInputNumberMeta.providers
]
wijmo.angular2.*モジュールのESMバージョンは、2020J v2からデフォルトで有効になっています。ESモジュールは、Angular 8以前のプロジェクトで、特定の使用シナリオで問題を引き起こす可能性があります。例えば、wjFlexGridCellTemplateまたはwjItemTemplateディレクティブ、またはMenuコンポーネントを含むカスタムコンポーネントテンプレートを使用して、Wijmoコンポーネントから継承されたコンポーネントがある場合です。この問題はAngular AOTコンパイラ(ViewEngine)が原因で発生するため、プロダクション(本番)バンドルでのみ発生することに注意してください。
この問題が発生した場合は、wijmo.angular2.*モジュールのESMバージョンを無効にする必要があります。これは、wijmo-esmユーティリティを使用して実現できます。通常は、オプションを渡さずにこのユーティリティを呼び出します。この場合、プロジェクトで使用されているAngularバージョンが自動的に検出され、8以前の場合はWijmo ESMモジュールが無効になり、9以降の場合は有効になります。ESMが無効になっている場合、AngularはCommonJSモジュールを使用します。
-disable または -enable オプションを指定して、ESMモジュールを無条件で無効または有効にすることもできます。ツールは、プロジェクトの node_modules/.bin フォルダーにインストールされます。推奨される使用方法は、npmの「postinstall」イベントから呼び出すことです。
"scripts": {
"postinstall": "wijmo-esm",
..........
}
手動で実行する場合は、プロジェクトのpackage.jsonのnpmスクリプトに追加します。
"scripts": {
"wijmo-esm": "wijmo-esm",
..........
}
その後、次のコマンドを使用して実行できます。
npm run wijmo-esm
または、オプションを指定する必要がある場合は次のコマンドを実行します。
npm run wijmo-esm -- -disable
使用可能なオプションに関するヘルプ情報を表示するには、次のコマンドを実行します。
npm run wijmo-esm -- -help
ツールの実行可能ファイルは、プロジェクトの次のパスにあります。
node_modules/@mescius/wijmo.angular2.directivebase/tools/wijmo-esm.js