notebook

都内でWEB系エンジニアやってます。

ag-gridで日付エディタを自作する

ag-gridの公式ドキュメントにサンプルはあるもののその場で作って設定するみたいな感じになっていたのでangularで再利用できるようにコンポーネント化してみます

  • 公式ドキュメント

Cell Editing: A Core Feature of our Datagrid

www.ag-grid.com

今回使うmodule

  • ag-grid-angular
  • ag-grid
  • ngx-bootstrap

環境

  • angular
npx ng -v

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 6.1.5
Node: 9.10.1
OS: linux x64
Angular: 6.1.4
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.7.5
@angular-devkit/build-angular     0.7.5
@angular-devkit/build-optimizer   0.7.5
@angular-devkit/build-webpack     0.7.5
@angular-devkit/core              0.7.5
@angular-devkit/schematics        0.7.5
@angular/cli                      6.1.5
@angular/tsc-wrapped              4.4.6
@ngtools/json-schema              1.2.0
@ngtools/webpack                  6.1.5
@schematics/angular               0.7.5
@schematics/update                0.7.5
ng-packagr                        1.7.0
rxjs                              6.2.2
typescript                        2.9.2
webpack                           4.9.2
  • node_module
"ag-grid": "18.1.2",
"ag-grid-angular": "18.1.0",
"ngx-bootstrap": "3.0.1",

やること

今回やることはこれだけです

  • cellEditorComponentの作成
  • cellEditorFrameworkに設定

cellEditorの設定方法はいくつかあるみたいです

  • Rendererに定義する
    • Editorのinterfaceを満たす関数を定義する
  • RendererFramework
  • gridOptionscomponentsに定義して呼び出す
    • interfaceを満たす関数をgridOptionscomponentsに適当なキー(サンプルだとdatepicker)で定義
    • columnDefcellEditorに定義したキーを設定

3つ目はサンプル見るまで知らなかったです

探した感じドキュメントにも載ってないのですがグリッドで使用するコンポーネントは一括でcomponentsに入れてあとは設定から呼び出すといった流れにしておけばスッキリしそうですね

今回は2つめでコンポーネント化していろんな画面で日付編集ができるようにします

  • ICellEditorComp

ag-Grid Components: Cell Editors

www.ag-grid.com

基本的には上記interfaceに沿って実装すればOKそうです

コンポーネントの作成

npx ng g component components/ag-grid-cell-editor.datepicker --skip-import
  • ts(一部抜粋)
public datepickerModel: Date;
@ViewChild('picker') bsDatepickerElement;
ngAfterViewInit() {
  this.bsDatepickerElement.show();
}

getValue(): string {
  return moment(this.datepickerModel).format('YYYY-MM-DD');
}
  • html
<input type="text"
       [bsConfig]="{ dateInputFormat: 'YYYY-MM-DD', containerClass: 'theme-dark-blue' }"
       [(ngModel)]="datepickerModel"
       #picker="bsDatepicker"
       bsDatepicker>

HTMLはこんな感じ

ngModelを使ってコンポーネントインスタンス変数と同期させてる感じですね

デフォルトだとダブルクリックで編集用のコンポーネントが展開されます

ngx-bootstrapのサンプルをそのまま貼っただけだとポップアップにフォームが出てくるのでそれをクリックしないとカレンダーが出てこない

なのでテンプレート側でbsDatepickerディレクティブのインスタンスをテンプレート変数に代入して

#picker="bsDatepicker"

ViewChildを使ってコンポーネント側でbsDatepickerインスタンスを取得して

@ViewChild('picker') bsDatepickerElement;

コンポーネント側でbsDatepickerディレクティブのメソッドを叩く

  this.bsDatepickerElement.show();

これでグリッド側で編集を開始した瞬間にカレンダーが開くようになりました

getValueは編集を終えた際に編集した値をag-grid側に渡すための関数です

今回は文字列を返すようにしました

カラム定義

      {
        headerName: '開始日',
        field: 'startDate',
        width: 120,
        editable: true,
        cellEditorFramework:AgGridCellEditorDatepickerComponent
      },

先程作ったコンポーネントを直接指定すればOK!

f:id:swfz:20180831101949g:plain  

無事日付編集機能を実装できました

サンプルは下記においておきます

NgxSample

https://swfz.github.io/ngx-sample/grid/reactiveswfz.github.io

まとめ

簡単にカスタムしたセルエディタを作成することができました

凝ったコンポーネントを作ればパターンが広がりそうですね

無料でもこの機能は使うことができるのでぜひお試ししていただけたらと思います

また、ただのコンポーネント作ってその中で無理やりgridのデータに対して変更かけるみたいなこともできるのですが、ag-gridの流儀にそってないので全部自前でやらなくてはなりません。

それに対してこちらの方法であれば値の変更やイベントの伝搬などもフォローしてもらえるのでだいぶ実装がらくになると思います。

余談ですが、これを作っている時点でngx-bootstrapのdatepickerはまだ開発版らしいのでこんなwarningが出てきました

BsDatepickerModule is under development,
      BREAKING CHANGES are possible,
      PLEASE, read changelog

まぁupdateで変えられたらその時対応しましょうw