NakamuraYoichiのblog

プログラマー NakamuraYoichi のアウトプット欲を満たすためのブログ。(iwanao さんの tweetにインスパイアされてこのブログを作りました。)

Telerik Kendo GridのデータとModelのデータを交換する

Telerik Kendo GridとModelのデータ交換をなるべくASP.NET MVCに任せたい,という話です。なぜModelとやり取りするのか,なぜGridから直接APIを呼ばないのか,というと,submitするまでデータベースを更新したくない,編集中の画面全体をキャンセルしたい,と思ったので。

Model→Grid

ロード時にModelからGridに渡すのは簡単で,Telerikのドキュメントにもありますが,次のようにします。

Html.Kendo().Grid(Model) @*Model自身が配列*@
Html.Kendo().Grid(Model.Hoges) @*メンバーHogesが配列*@

Grid→Model

submit時にGridからModelに渡すには,次の記事を参考にしました。Gridに限らず応用できる場面は多いと思います。

カラムのClientTemplateでname属性を例えば次のように付ければよさそうです。

.ClientTemplate("<input type='hidden' name='Hoges[0].Id' value='#= Id #' />#= Name #");

添え字を取得するjavascript functionを用意します。dataSourceのindexOfメソッドを使います。

function getIndexOf(dataItem) {
var grid = $('#grid').data('kendoGrid');
return grid.dataSource.indexOf(dataItem);
}

結果,ClientTemplateは次のようになります。

.ClientTemplate("<input type='hidden' name='Hoges[#= getIndexOf(data) #].Id' value='#= Id #' />#= Name #");

チェックボックス

チェックボックスは少し難しくて,value属性とchecked属性の両方を設定しないとGrid→Modelが行かないです,たぶん。事情はこのへんの記事で。

offのときにfalseを送れるように,ってことでしょうか。hiddenを別建てする方が正式なのかもしれません。とりあえず,if-elseを使って次のようなClientTemplateになります。

.ClientTemplate(
"# if (Flag) { #" +
"<input type='checkbox' name='Hoges[#= getIndexOf(data) #].Flag' value='true' checked />" +
"# } else { #" +
"<input type='checkbox' name='Hoges[#= getIndexOf(data) #].Flag' value='false' />" +
"# } #");

グリッド内のチェックボックスを直接編集するためには次のようなコードが必要だと,Telerikのフォーラムで紹介されています,が...

$('#grid .k-grid-content').on('change', 'input.chkbx', function (e) {
  var grid = $('#grid').data('kendoGrid'),
    dataItem = grid.dataItem($(e.target).closest('tr'));
  dataItem.set(e.target.name, this.checked);
});

が,これは'Hoges[0].'を付けない場合の書き方です。今回はデータ交換のために'Hoges[0].'を付けたので,次のようにしてみました。

$('#grid .k-grid-content').on('change', 'input.chkbx', function (e) {
  var grid = $('#grid').data('kendoGrid'),
    dataItem = grid.dataItem($(e.target).closest('tr'));
  dataItem.set(e.target.name.split('.').pop(), this.checked);
});

inputの方にclass='chkbx'を追加するのを忘れずに。

.ClientTemplate(
"# if (Flag) { #" +
"<input type='checkbox' name='Hoges[#= getIndexOf(data) #].Flag' value='true' checked class='chkbx' />" +
"# } else { #" +
"<input type='checkbox' name='Hoges[#= getIndexOf(data) #].Flag' value='false' class='chkbx' />" +
"# } #");

ソフトウェアとマラソン

ソフトウェア技術者はマラソンを走るとよい,という英語の記事があったのでざっくり紹介します。

準備
長い距離を走るには特別な準備が必要。アーキテクチャの選択も同じ,目的を持ち,調査と原則に基づいて行おう。
リスク管理
実際のレースでは不測の事態が起こるもの。アーキテクチャの弱点を見つけてリスクを識別して注意を払いながら進めよう。
休憩
レース途中で歩いたりスピードを落としたりして休むことも必要。休みの日は休むこと。ときどき別のプロジェクトでリフレッシュしよう。
情熱
スタート時は元気,30kmを過ぎたら地獄,ゴールが見えるとラストスパートがかかる。プロジェクトも同じ,マラソンで精神を鍛えておくといいんじゃないかな。

(原文) What I learned about software architecture from running a marathon by Ted Malaska

筆者のテッドさんはダイエットのために走り始めたそうですが,「走った分だけ食っていいんだぜ」とも言っています :-D

Closure Linter を Windows 10 にインストール

Closure Linter を Windows 10 にインストールしてみました。その作業記録です。

※注意: 前半の手順は結局無駄になります。それぞれの節に「正」「偽」と印を付けてあります。


経緯


Google JavaScript Style Guideに準拠して書きましょう、ということになりました。しかし、ルールを始めから全部頭に入れるのは難しいし、チェックも面倒です。ググって Closure Linter というのが出てきたので、試してみることにしました。

環境は次の通りです。

  • Windows 10(Hyper-V の仮想PC)
  • インターネット接続なし(内部ネットワークでホストとのみ接続)

ホストでファイルをダウンロードして、仮想PCに渡すことはできる状態です。直接インターネットに接続できるようにするのは面倒な手続きが要りそうだったのです。


Closure Linter のページ

Google Developers
https://developers.google.com/closure/utilities/index
GitHub
https://github.com/google/closure-linter

(偽) Python 3 のインストール

(作業時点の)最新 3.5.0 をインストーラーでインストールしました。

実行してみます。 python に PATH を通します。なんだかすごく深いところにインストールされてしまいました。 (追記: インストーラーの一番最初の画面で「Customize installation」を選択すると、インストールするパスを指定することができます。 同じく最初の画面で PATH に追加するよう指定することもできるようです。)

> SET PATH=%PATH%;C:\Users\username\AppData\Local\Programs\Python\Python35
> python
Python 3.5.0 (...

起動を確認しました。Ctrl-Z, Enter で終了します。


(正) Closure-linter のダウンロード

Closure-linter のインストール方法は、

> pip install https://closure-linter.googlecode.com/svn/trunk/

とか、

> easy_install http://closure-linter.googlecode.com/files/closure_linter-latest.tar.gz

というコマンドが紹介されています。 しかし、今回インターネット接続がありませんので、ダウンロードした圧縮ファイルを展開して、

> python setup.py install

というコマンドでやります。

GitHub から closure-linter-master.zip というのを落とします。


(偽) Closure-linter のインストール

.zip を解凍して、

> python setup.py install

入りました。 実行ファイルは、コンピューターの中を検索して見つけました。 ...\Python35\Scripts\gjslint.exe です。 よく見ると、同じフォルダーに easy_install と pip もあります。

gjslint を実行してみると、

> gjslint --help
Traceback (most recent call last):
  ...
pkg_resources.DistributionNotFound: The 'python-gflags' distribution was not found and is required by closure-linter

python-gflags というのが足りないようです。


(正) python-gflags のダウンロード

PyPI で python-gflags を検索します。 おっと、.zip がありません、.tar.gz と .egg だけです、どうしましょう。 ググります... tar は 7-zip.org 7-Zip で解凍できるんですね。幸運にもこれはインストール済みでした。


(偽) python-gflags のインストール

setup.py のフォルダに移動して、

> python setup.py install

途中でエラーが出た気がしますが、一応最後まで行ったし、よく分からないので無視:p


(偽) closure-linter の実行

> gjslint --help
Traceback (most recent call last):
  ...
  File "...\closure_linter\gjslint.py", line 176
    print '%s: %d' % (path, len(path_errors))
                 ^
SyntaxError: invalid syntax

こんなエラー、どうにかできるのでしょうか。 ググります ... この print は python 2 の書き方なので、3 じゃダメだとか。本当に? いいでしょう、Python 2 を入れ直しましょう。


(正) Python 2 のインストール

実際に私が使ったのは次のバージョンです。

Python 2.7.10
Windows x86-64 MSI installer
ファイル名: python-2.7.10.amd64.msi

深いところに入ってしまった Python 3.5 と違って c:\Python27 というフォルダに入りました:)

新しいコマンドプロンプトを起動します。PATH を通します。

> SET PATH=%PATH%;C:\Python27

Python を起動します。

> python
Python 2.7.10 (...

起動を確認しました。Ctrl+Z, Enter で終了します。


(偽) closure-linter のインストール

closure-linter のインストールのやり直しです。Python27 の方にインストールします。

> python c:\temp\closure-linter-master\setup.py install
running install
...
error: Coud not find suitable distribution for Requirement.parse('python-gflags')

python-gflags が必要でした。


(偽) python-gflags のインストール

python-gflags を Python27 の方にインストールします。

> python c:\temp\python-gflags-2.0\setup.py install
running install
...
error: can't copy 'gflags2man.py': doesn't exist or not a regular file

ファイルが不足!? いや、 gflag2man.py は python-gflags-2.0 フォルダ直下にあります。


(正) python-gflags のインストール

カレントフォルダを移動して作業しましょう。

> cd c:\temp\python-gflags-2.0
> python setup.py install
running install
...
Finished processing dependencies for python-gflags==2.0

成功です。


(正) closure-linter のインストール

何度目かの closure-linter のインストールです。

> cd c:\temp\closure-linter-master
> python setup.py install
running install
...
Finished processing dependencies for closure-linter==2.3.19

成功です。


(正) closure-linter の実行

closure-linter の動作確認です。

> cd c:\python27\scripts
> gjslint
0 files checked, no errors found.

> gjslint --help

USAGE: C:\Python27\Scripts\gjslint-script.py [flags]
...

良さそうです:) 実際に lint かけてみます。

> gjslint c:\temp\hoge.js
----- FILE  :  c:\temp\hoge.js -----
...
Found 388 errors, includeing 1 new error, in 1 file (0 files OK).

出来ました:D


fixjsstyle の利用

fixjsstyle も試してみます。

> fixjsstyle c:\temp\hoge.js
Fixed 370 errors in c:\temp\hoge.js
...

出来ました。


easy_install の利用

一応 easy_install も試してみます。

> cd c:\Python27\Scripts
> easy_install c:\temp\python-gflags-2.0.ta.gz
Processing python-gflags-2.0.tal.gz
...
Finished processing dependencies for python-gflags==2.0

easy_install も使えそうです。


まとめ

  1. Python をインストール。Python は 3 ではなく 2。
  2. python-gsflags をインストール。
  3. closure-linter をインストール。
  • Python のツールのインストール方法は(オフラインでは)、
    > python setup.py install
    または、
    > easy_install hoge.tar.gz
  • 困ったら、カレントディレクトリを移動したり、PATH を通したりしてみる。
  • Python のツールは Scripts というフォルダーに入る。
  • .tar.gz は怖くない。
記事検索
  • ライブドアブログ