Thread Rating:
  • 472 Vote(s) - 2.79 Average
  • 1
  • 2
  • 3
  • 4
  • 5
入力チェックについての質問です
04-03-2014, 05:52 PM, (This post was last modified: 04-03-2014, 06:33 PM by rom.)
#1
入力チェックについての質問です
初めまして最近Curlを学習し始めた者です。
ネットでCurlを調べると、行き着く先は大体ここのサイトの情報となります。
とても勉強になる回答やソースコードが豊富なので自分も参加してみました。

~以下質問内容~

ボタン押下時に表示されているRecordGrid内のデータを入力チェックをしたいです!

~現在の動作~
・現在recordgridを使用してデータベースの値を取得しています。
・各セルでの編集をして「保存」ボタンを押下した場合に画面に表示されているRecordGrid内の値をDBに登録する
・各セルFocusOut時に入力チェックをしてNG時はセルの背景を変更し、強調表示をする

~困っている点~

名前列には数字は入力チェックに引っかかるようになっています。
数字を入力して他のセルをクリックするとエラーメッセージを表示し、エラーセルにフォーカスを戻します。

しかし、数字を入力してそのまま「保存」ボタン押下時にはFocusOutの処理は行われずに
そのまま数字がデータベースに保存されてしまいます・・・

ボタン押下時の処理をどう変更すればよろしいのでしょうか?
ご教授ください。

04-03-2014, 06:35 PM,
#2
RE: 入力チェックについての質問です
{import * from CURL.LANGUAGE.REGEXP}

{define-class public Check-name {inherits StandardStringCell}
{constructor public {default}
{construct-super}
}
||置換前
field before_text:String=""

||置換後(数字)
field after_text_suuji:String = ""

||チェックする値(数字)
field chk_suuji:String = "[0-9]"

{method public {note-grid-focus-out}:void
{super.note-grid-focus-out}

||フォーカスを受けていたセルの値を保存する(置換前)
set self.before_text = {String {super.get-data}}

||置換する(数字)
set self.after_text_suuji =
{regexp-subst
self.chk_suuji
,self.before_text
,""
,replace-all?=true
}

||
{if {self.before_text.equal? self.after_text_suuji}
then
{set self.background = "white"}
else
{popup-message "・数字が入力されています"}
{after 0s do {self.become-active}}
{set self.background = "red"}
}
}
}

{let people:RecordSet=
{RecordSet
{RecordFields
{RecordField "名前"}
,{RecordField "年齢"}
}
,{RecordData 名前 = "テスト君" , 年齢 = "25"}
,{RecordData 名前 = "テストさん", 年齢 = "37"}
}
}

{let test:RecordGrid=
{RecordGrid
record-source = people
,{RecordGridColumn "名前" ,width=50,cell-spec = Check-name}
,{RecordGridColumn "年齢" ,width=50}
}
}

{let hozon:CommandButton=
{CommandButton
label="保存"
,{on Action do
{people.commit}
}
}
}

{value
{VBox
test
,hozon
}
}
04-04-2014, 10:05 AM,
#3
RE: 入力チェックについての質問です
上記のようなコードを書いており、「保存」ボタン押下時にエラーチェックをしたいです。。。
04-06-2014, 09:24 PM,
#4
RE: 入力チェックについての質問です
自分もRecordGridのバリデーションチェックはどのようにするのがよいのか悩んでいるのですが・・・

FocusOutしたときにnote-grid-focus-outが呼ばれない件は、フォーカスとグリッドフォーカスは
まったく同じものではなくて、フォーカスがRecordGridとは別のコントロールに移動しても、
破線で囲われたセルにグリッドフォーカスがあるのでは?

FocusOutはon-focus-outメソッドをオーバーライドすれば取れるのではと思うのですが、
ダイアログを表示した際などにもフォーカス移動が発生するので制御が面倒そうです。

ただ、本来やりたかったことを考えると値を入力した際のチェックなので、Record更新時の
update-dataを使うというのはどうでしょうか?

他に考慮しなければならないことがありそうですが、とりあえずupdate-dataを使うように
コードを変更してみました。
Code:
{import * from CURL.LANGUAGE.REGEXP}

{define-class public Check-name {inherits StandardStringCell}
  {constructor public {default}
    {construct-super}
  }
  ||置換前
  field before_text:String=""
  
  ||置換後(数字)
  field after_text_suuji:String = ""
  
  ||チェックする値(数字)
  field chk_suuji:String = "[0-9]"
  
||--  {method public {note-grid-focus-out}:void
||--    {super.note-grid-focus-out}
  {method public {update-data val:any}:#DataException
    def de = {super.update-data val}
    {if-non-null de then
        return de
    }
    
    ||フォーカスを受けていたセルの値を保存する(置換前)
    set self.before_text = {String {super.get-data}}
    
    ||置換する(数字)
    set self.after_text_suuji =
        {regexp-subst
            self.chk_suuji
            ,self.before_text
            ,""
            ,replace-all?=true
        }
    
    ||
    {if {self.before_text.equal? self.after_text_suuji}
     then
||++    {set self.background = "white"}
        {unset self.background}
     else
        {popup-message "・数字が入力されています"}
        {after 0s do {self.become-active}}
        {set self.background = "red"}
    }
    
    {return null}
  }
}

{let people:RecordSet=
    {RecordSet
        {RecordFields
            {RecordField "名前"}
            ,{RecordField "年齢"}
        }
        ,{RecordData 名前 = "テスト君" , 年齢 = "25"}
        ,{RecordData 名前 = "テストさん", 年齢 = "37"}
    }
}

{let test:RecordGrid=
    {RecordGrid
        record-source = people
        ,{RecordGridColumn "名前" ,width=50,cell-spec = Check-name}
        ,{RecordGridColumn "年齢" ,width=50}
    }
}

{let hozon:CommandButton=
    {CommandButton
        label="保存"
        ,{on Action do
             {people.commit}
         }
    }
}

{value
    {VBox
        test
        ,hozon
    }
}
04-07-2014, 12:56 PM,
#5
RE: 入力チェックについての質問です

romさんの質問は、RecordGrid を利用する際に多くの方がぶつかる問題だと思います。
とくに、dyoshidaさんもおっしゃられているように「チェック機能をどのように設計するのか」という
問題にかかわってくるので、かなり深いところに突っ込まなくてはならず、
設計の知識にうとい私では、簡潔な回答には至りませんでした。


まず、質問のポイントをまとめると、下記2点になるかと思います。
①フォーカスアウト時にチェックをかけるには?
②ボタン押下時にチェックをかけるには?

そして、これらには、隠れている問題があり、
A.エラー状態を表現するにはどうするか
B.エラー状態を保持するにはどうするか
を考える必要があります。

さらに、汎用的な設計として、
α.誰がチェックするのか
β.いつチェックするのか
ということ問題に波及していきます。


①についての回答としては、私も、dyoshidaさんのように、
update-data にすることが直接的な解決方法かな、と思うのですが、
ただ、この解決方法には、隠れた問題Aがあります。

問題Aの発生手順
1.レコードを100レコード作成する
2.任意のレコードで、エラーにする(セル背景が赤になる)
3.グリッドの縦スクロールを操作する
4.エラーでないセルの背景が赤く表示される ←問題発生

この問題は、RecordGrid のセルのインスタンスが、再利用されていることから発生しています。

再利用されているセルが、現在表現すべきエラー状態を正常に表現するには、
セルの描画メソッドである、refresh-data メソッドを利用する必要があります。

しかし、描画の度にエラーを判断する処理を行うと、グリッド全体のパフォーマンスが低下する恐れがあり、
単純に update-data に移管した処理内容を、refresh-dataに移管する、というのはおすすめできません。
これが、隠れた問題B、ということになります。

ではどうすればよいか、というと、私は、レコードに「エラー状態」というフラグを持ち、
描画とチェックの機能を分けて実装する方法が良いと思っています。

つまり、チェックメソッドで、チェック処理とエラー状態フラグの切り替えを行い、
描画メソッド(refresh-data)では、エラー状態フラグの結果だけを参照するようにする、ということです。

もっとよい設計があるかもしれませんが、下記のスレッドで、セル単位でエラー状態を保持するサンプルコードが載っています。
http://communities.curl.com/showthread.php?tid=905


もうひとつの問題②については、上記で作成したチェックメソッドを、
ボタン押下時に呼び出す仕組みを用意すればよいかと思います。

romさんのソースでは、カスタムセルにチェックロジックが入っているので、
グリッド内の全セルに対してチェックをかけるとすると、
1.グリッドに、ボタン押下時に呼ばれるチェックメソッドを用意し
2.チェックメソッド中で RecordGrid.ui から、RecordGridUI を取得
3.RecordGridUI.get-cell-at で全セルをまわしながらチェックする
4.一つでもエラーがあれば、RecordSet.commit をコールしない
という方法になりそうですが、
案外、セルをインスタンス化するコストは無視できないので、
チェックロジックはRecordGridColumn に持たせ、チェックロジックに渡すデータはReocrd から取得する、
という設計のほうがよいかもしれません。
これが設計上の問題αになります。

ただ、ボタン押下以前に、すべてのグリッドが、必ず1度以上チェックロジックをとおっている、という前提があれば、
上記のように、セルをまわさなくても、レコードにエラー状態が保持されているはずなので、
ボタン押下時は、レコードのエラーフラグだけ参照すればよいかもしれません。

フォーカスアウト時、ボタン押下時の両方でチェックすべきか、どちらか片方だけでよいのか、
つまり、いつチェックすべきか、という問題βにかかわってくるわけです。

「エラー時にフォーカスを戻すべきか」という内容についても
思うところはあるのですが、こうあるべき、という結論には至っていません。
そのあたりも含めて、Tech blog にネタを提供できたらと思っています。
04-07-2014, 01:36 PM,
#6
RE: 入力チェックについての質問です
>dyoshidaさん
>umemuraさん

お返事ありがとうございます!

早速試してみて勉強します!!

しかしチェックの一つにも設計段階の話があるとは驚きでした。。。

事実、設計段階からこの問題を発見することが出来たのなら早い段階で処理出来たと思います。。。

Recordgrid系は複雑で勉強が難しいです><

今はソースをいじって暗中模索で開発をしているので

"慣れ"が必要だと感じました!

本当にありがとうございました!

まだまだ質問をすることがあると思いますが、

その時は何卒宜しくお願いします。

04-07-2014, 06:08 PM,
#7
RE: 入力チェックについての質問です
色々試してみましたが勉強不足の為、撃沈です・・・

重複チェック+文字数チェック+文字種類チェック..etc

頭の中での構想は膨らむばかりですが、手を動かそうと思うと全然進まない自分が嫌になりますorz

皆様のように質問に答えられるようになり当コミュニティを盛り上げたいですね!!!

04-15-2014, 11:31 AM,
#8
RE: 入力チェックについての質問です
こんにちは!

久しぶりにCurlの入力チェックについて挑戦してみた結果を報告します

★実現したい動作
・データ保存時(DB登録)各セルに入力チェックをつけたい

★実装機能
・cell-specを使用し、各セルFocus-out時に入力チェックを実装させた!

★問題点
・入力チェックに引っかかる文字を入力し「保存」ボタン押下時に
Focus-outにならないため入力チェックが動作しない

★解決策
・refresh-dataを使用しセルの情報(record-indexとfield.nameとcell-data)を変数に保存し
「保存」ボタン押下時にfield.nameに応じた入力チェックをcell-dataに適用し
エラー時にrecord-index行を強調表示する

=========
現在はこのような対応で一時解決?までいたりました!
ありがとうございます!

・・・しかし!
新たな問題点が発覚・・・
現在セルのfocus-out時にエラーの場合
エラーセルにフォーカスを戻し、強調表示をしているのですが、
エラーセルにフォーカスが戻らない現象が起きました。

=オペレーション手順=
★正しい動作
①カラム:A 1行目のセルに「@」を入力
②スクロールをせず隣のセルを選択
③ポップアップでエラーの旨を表示
④A-1セルにフォーカスが戻る

★問題動作

①カラム:A 1行目のセルに「@」を入力
②スクロールをしてカラム:A 9行目のセルを選択
③ポップアップでエラーの旨を表示
④A-1セルにフォーカスが戻らずに
 ②で選択したセルにフォーカスが移ってしまう
 強調表示されるはずのセルが違うセルになっている

上記での問題は考えてみて時間がかかるようでしたら再び質問として建てようと思っています!
Code:
{import * from CURL.LANGUAGE.REGEXP}

{define-class public Check-at-mark {inherits StandardStringCell}
  {constructor public {default}
    {construct-super}
  }
  ||置換前
  field before_text:String=""

  ||置換後(数字)
  field after_text:String = ""

  ||チェックする値(数字)
  field chk_at-mark:String = "@"

  {method public {note-grid-focus-out}:void
    {super.note-grid-focus-out}

    ||フォーカスを受けていたセルの値を保存する(置換前)
    set self.before_text = {String {super.get-data}}

    ||置換する(@マーク)
    set self.after_text =
        {regexp-subst
            self.chk_at-mark
            ,self.before_text
            ,""
            ,replace-all?=true
        }

    ||判定
    {if {self.before_text.equal? self.after_text}
     then
        {unset self.background}
     else
        {popup-message "・「@」が入力されています"}
        {after 0s do {self.become-active}}
        {set self.background = "red"}
    }
  }
}

{let test_set:RecordSet=
    {RecordSet
        {RecordFields
            {RecordField "A"}
            ,{RecordField "B"}
        }
        ,{RecordData A = "1" , B = "100"}
        ,{RecordData A = "2" , B = "200"}
        ,{RecordData A = "3" , B = "300"}
        ,{RecordData A = "4" , B = "400"}
        ,{RecordData A = "5" , B = "500"}
        ,{RecordData A = "6" , B = "600"}
        ,{RecordData A = "7" , B = "700"}
        ,{RecordData A = "8" , B = "800"}
        ,{RecordData A = "9" , B = "900"}
    }
}

{let test_grid:RecordGrid=
    {RecordGrid
         record-source = test_set
        ,width  = {make-elastic minimum-size = 200 }
        ,height = {make-elastic minimum-size = 150 }
        ,{RecordGridColumn "A" ,width=80,cell-spec = Check-at-mark}
        ,{RecordGridColumn "B" ,width=80,cell-spec = Check-at-mark}
    }
}

{let hozon:CommandButton=
    {CommandButton
        label="保存"
        ,{on Action do
             {test_set.commit}
         }
    }
}

{value
    {VBox
        test_grid
        ,hozon
    }
}

04-15-2014, 01:08 PM,
#9
RE: 入力チェックについての質問です
RecordGridのエラーチェックについての重要な点を上でumemuraさんがまとめてくださっているのですが
今回の問題もそこに書かれていることに起因しているかと

 >この問題は、RecordGrid のセルのインスタンスが、再利用されていることから発生しています。

RecordGridの行(とその中のセル)は全レコード分存在するわけではなく、見えている表示分+αだけ存在し、
スクロールアウトして見えなくなった行のセルは別のレコードの表示用に再利用されるようです。
このため、エラーチェックに必要な値(または結果)の保存場所にセルは不適当ということになります。

このあたりの話はこの記事が非常に参考になりました
http://codezine.jp/article/detail/6113

また、スクロールアウトしているエラーのあるレコードは、そのレコードのインデックスを指定して
request-current-record-changeメソッドを呼べば表示できるのでは。
04-16-2014, 01:24 PM,
#10
RE: 入力チェックについての質問です
>dyoshidaさん

返答有難うございます。

RecordGrid内のフォーカスを自由に設定できるコードを書いてみようと思います!

  >また、スクロールアウトしているエラーのあるレコードは、そのレコードのインデックスを指定して
   request-current-record-changeメソッドを呼べば表示できるのでは。



上記のやり方も試してみたいと思います!(理解できるのか不安です。。。)




Forum Jump:


Users browsing this thread:
1 Guest(s)

MyBB SQL Error

MyBB has experienced an internal SQL error and cannot continue.

SQL Error:
1017 - Can't find file: 'mybb_threadviews' (errno: 2)
Query:
INSERT INTO mybb_threadviews (tid) VALUES('1063')