フィールドを使って列の見出しを兼ねたソートボタンを作る際の、見栄えの工夫についてです。なるべく少ない部品でやってみます。
いきなり「フィールドを使って列の見出しを兼ねたソートボタンを作る際の」と言っても何のことやらわかりませんね。FileMakerソートボタンに関する過去記事の補足なんですが、見に行かなくても済むように最初にここでまとめておきます。
列の見出しをソートボタンにする
ポータルやリスト表示のレイアウトで、ヘッダにあたる部分に列の見出しを配置し、それをクリックすることでソートできるようにしたいと誰しもが思います。
見出し部分がボタンになっていてクリックする度に昇順と降順がトグルでソートするという、よく見かける動作をします。
これを作る方法はいろいろありますが、最も簡単だと思うのがフィールドそのものをボタンにしてしまうやり方です。
参考ビデオ→ 効率的な カスタム App開発の基本手法を考察する – 2023年版
過去投稿 → FileMaker ソートボタン
実際の話、参考ビデオがほぼすべてで、ご覧になればそれで済む話ですが、ここでは補足的な若干の注意点と、レイアウト配置についてよりシンプルなもの作りを試みます。
フィールドそのものを使用する
ボタンではなく、ソートしたいフィールドを使用します。リストの上部、目的の場所にフィールドそのものを配置します。
持ってきたフィールドにトリガをセットします。OnObjectEnterにスクリプト「ソート」をあてがいましょう。
ソートのスクリプト
ソートスクリプトには次の仕事をさせます。
- グローバル変数に応じたソート順の分岐と、ソート後のグローバル変数上書き
- ソート実行
グローバル変数は、ソートしたフィールド名とソート潤の記録です。これを元に適切なソートを行い、そして上書きします。
ソートの実行は、スクリプトステップ「レコードをフィールド順でソート」を使います。このステップはフィールドを指定しないでおくと現在アクティブなフィールドをソート対象にしてくれます。
スクリプトは以下です。
// 今クリックしたフィールド名 変数を設定 [ $f; 値:Get ( アクティブフィールドテーブル名) & "::" & get ( アクティブフィールド名 ) ] If [ $$orderBy = $f ] // $$orderByと今クリックしたフィールドが同じなら、現在と逆のソートを行う If [ $$order = "DESC" ] // 現状$$order が降順なら昇順でソート レコードをフィールド順でソート [ 昇順 ] 変数を設定 [ $$order; 値:"ASC" ] // ソート順を$$order に記録 Else // 現状$$order が昇順なら降順でソート レコードをフィールド順でソート [ 降順 ] 変数を設定 [ $$order; 値:"DESC" ] // ソート順を$$order に記録 End If Else // $$orderBy とクリックしたフィールドが異なっている($$orderByが空を含む)なら、デフォルトのソート順を実行 レコードをフィールド順でソート [ 昇順 ] // $$orderBy(フィールド名)と$$order(ソート順)を記録 変数を設定 [ $$order; 値:"ASC" ] 変数を設定 [ $$orderBy; 値:$f ] End If
1行目でクリックしたフィールドの完全修飾名を取得しています。
Get ( アクティブフィールドテーブル名) & "::" & get ( アクティブフィールド名 )
アナログチックな取得方法ですが、ここでGetFieldName を使わないようにしましょう。後ほど。
グローバル変数(現在のソート状態)に応じて if で振り分けソートを実行してからグローバル変数を上書きします。
$$orderBy(現在のソート対象)が今クリックしたフィールドと同じなら、$$order(現在のソート順)の逆を実行します。異なっていれば、お好みのデフォルト順でソートします。
いくつかの留意点
いくつか留意する点があります。
インスペクタでフィールド入力を可に
インスペクタのフィールド入力でブラウザモードがチェックされていないとクリックも受け付けず動作しないので、チェックしておきます。
関連テーブルでフィールドが空だと無反応
関連テーブルのフィールドで、現在レコードの該当フィールドに内容がない場合、ソートが働きません。レイアウトテーブル内のフィールドなら動作します。
空でも動かせるようにするには、リレーション設定で「作成を許可」にしておく必要があります。
「ソートのためだけに作成を許可するわけにはいかんな」という場合はこの方法を諦め、そのフィールドだけ個別に扱いましょう。
見栄えを作る
さて、このボタンのような挙動のフィールド、なんせフィールドなので見た目をボタンみたいにしましょう。
ネタ元の参考ビデオと以前の投稿では、次のような複雑な構成でした。
ソート状態を示すアイコン的なものを個別に隠すことができないので、目隠し用フィールドを覆い被せるという強引な方法です。
正直、このオブジェクト数の多さはうんざりで、「目隠し用」が特にいただけません。もっと簡略化できないか?できます。
というのが、本投稿の目的です。やっとここまで来ました。
目隠しフィールド不使用でシンプルに
そんなわけで、以前の投稿で気になっていた無意味に複雑な見栄え表現を、ここで改めます。
完成品の例は以前のとまあ同じです。
二つ並べていますが、その違いはソート順を示すのがアイコンか文字列かの違いです。文字列にすれば使用オブジェクト数を1個減らせます。
固まりを分解して縦に並べるとこんなです。「目隠し用」要りません。
これなら許容範囲じゃないでしょうか。実際の運用では上図の固まりをグループ化しておいて、複製してフィールドだけ指定し直すことで汎用的に使い回せます。
アイコン
最下層にソート順を示すアイコン的なボタンを置いてます。ボタンの働きは「何もしない」で、見た目を作ることだけが目的です。
アイコンを使えば見た目は良いですが昇順と降順の二つ必要です。インスペクタの「隠す」で $$order に準じます。
文字列のほうは、ボタンバーを使って「隠す」の代わりに if ( $$order = “ASC” ; “△” ; “▽”) 的な計算式で表示を切り替えます。
このアイコン、$$order を元にソート順表示を決定させているだけなのでフィールドごとに表示・非表示を管理できません。全部に配置して上からフィールドをおっ被せて隠すを実現します。
そもそもの話ですが、フィールドのラベルごとにすべてアイコンが必要かどうかを考えます。ラベル全体の端だけにあっても悪くないです。
それでいいなら、さらにシンプルな部品だけで済みます。
フィールド
ソート順の上に配置するのが主人公のソートフィールドです。
フィールド状態のままではただのフィールドなので、ボタン的な表示のために一工夫入れます。
ネタ元の参考ビデオや以前の投稿では、フォントサイズを 1に、基本オフセットを-10 にして内容が見えないようにしていました。逆にフォントサイズを500とか大きくすることでも隠せます。
あと、スクロールをONにして「スクロールする場合」にしておきます。こうしておかないとたまにクリックした瞬間ドバッとフィールドが膨れることがあります。
背景色
インスペクタで背景色を付けておくことが前提ですが、このとき全体の背景色との関係に注意します。どう注意するかというと、フィールドの背景色が不透明度100%であるときとほぼ透明であるときに、フィールドに違和感を感じさせないような色を設定します。
通常は背景色100%で塗りつぶされています。ソート対象になれば透明(図では僅かに青み)になり、下に配置したソート順アイコンが見えるようになるという案配です。
これはボディの背景色と関係が深いので、配色計画全体のお話かもしれません。ボタンの背景にだけ、図形オブジェクトを置いてしまうという手もありますね。
条件付き書式
ソートフィールドの背景色を変えるため、条件付き書式を仕込みます。現在のソート状態を記録した $$orderBy と同じ名前のフィールドなら、背景色をほぼ透明にします。
ここに罠と注意点もありますが、とりあえず話を進めます。
GetFieldName ( Self )
GetFieldName関数で「GetFieldName ( Self )」が使えることを知ったのはわりと最近です。この関数はいろいろよく判らないし不具合もあって気に入らないのですが、 GetFieldName ( Self ) = $orderBy という条件式が使えるのはこの関数だけ。
$$orderBy とフィールドSelfが等しければ透明に
条件付き書式で「$$orderBy とフィールド名が等しければ」、背景色を透明に近づけます。その結果背面にあるソート順のアイコンが見えるようにします。
以前、わざわざ同じフィールドを重ねて目隠し用としていましたが、今回はフィールドそのものに目隠しの機能を持たせるということでした。「目隠し用」なんてフィールドを使わなくてもいいのでこっちのほうが良くないですか?
注意点
ひとつだけ残念な注意点があります。この方法、レイアウトテーブル内のフィールドでしか使えません。関連テーブルのフィールドでは正しく動作しません。
ソートしたいフィールドが関連テーブルの場合は汎用性を諦め、個別具体的にチクチク書いて特定一意のフィールドを隠したり表示する仕組みを作るしかありません。覚悟をお願いします。
以上、だいたい終わりです。以前の投稿でも気になっていた部品点数を減らすことができました。
最後に、GetFieldName について補足しておきます。
GetFieldName の罠と注意点
このソートボタンフィールドの仕組み、参考ビデオでおっしゃっているのと同じく、とにかく汎用性を求めています。「フィールドを選ぶ」以外にすることは一切ないという目標ですがレイアウト上の見栄えを作ることに関してはそれが崩れます。
GetFieldName ( Self )
これが使えることで、$$orderBy と比較して見た目を制御できました。ところが、これが使えないケースがあります。
GetFieldName の問題
GetFieldName関数には不具合があり、関連テーブルのフィールドでは機能しません。結果が「?」になります。
アクティブフィールドが関連テーブルからのものである場合、計算式 GetFieldName (Evaluate (Get (アクティブフィールド名))) は “?” を返す – Claris
Claris社ではこの問題を認識されていますが未だ修正される気配はありません。
GetFieldName ( Self ) が正しく結果を返さないので為す術もありません。
GetFieldName の機能と代替
GetFieldName の使い道としては次の三つがあると思います。
- アクティブなフィールドの完全修飾名を取得する
- 指定したフィール名の完全修飾名を取得する
- Self で己自身の完全修飾名を取得する
1 と 2 は、代替の計算式が作れます。この投稿の上の方でも、1 の代わりに Getアクティブフィールド系を使った記述があります。
3 の Self だけは代替不可能です。どう頑張っても無理でした。
※ もし 3 の動作をする計算式をご存じの方は是非とも教えてください
己の完全修飾名をゲットしたくとも、関連テーブルのフィールドでは不可能という現実を知っておくことが重要です。
対処
対処はありませんので、関連テーブル内フィールドを使う場合は「汎用」という言葉をあなたの脳から捨てます。
汎用性を諦め個別具体的に、例えばフィールド名を直打ちするとか、オブジェクト名を指定するとか、地道に作業します。
汎用至上主義や汎用教洗脳にどっぷりハマった人間には身を切る辛さですが、冷静に考えれば単に個別に指令を書けば良いだけなので、何がそれほど問題だったのか?と我に返るかもしれませんよ。
ということで、以前の投稿(FileMaker ソートボタン) の続編的な本投稿でした。実際にはほんの僅かな部分がアップデートされただけで、ほぼ内容ダダ被りになりましたがお気になさいませぬよう。