拡張フィールドの仕組み
拡張フィールド(ExtendedField)を使うと、テーブルの項目設定を変えずに、一覧画面のフィルタエリアに独自の入力欄を追加したり、ビュー拡張エリアに任意の入力欄を置いたりできます。入力値は SqlParam で拡張 SQL の @パラメータ名 として渡せるため、view.OnSelectingWhere と組み合わせると標準機能では難しい検索フィルタを作れます。対象はバージョン 1.4 以降です。
SQL 例の読み方
DBMS 名のない SQL は、3 DBMS で共通の構文を使った説明用の抜粋です。プリザンターは MySQL 接続でも ansi_quotes を設定するため、識別子の二重引用符が使えます。DB のコンソールで直接実行するときの引用符・パラメータの扱いは DBMS ごとの SQL の書き方 を参照してください。... を含む例は実行用 SQL ではありません。
表示場所(FieldType)
拡張フィールドは次の 2 つの表示場所に対応しています。
| FieldType | 表示場所 | 用途 |
|---|---|---|
Filter | 一覧のフィルタエリア(#ViewFilters) | 標準のフィルタ項目と並べて独自のフィルタ入力欄を追加する |
ViewExtensions | ビュー拡張エリア(#ViewExtensions) | ビューに紐付く任意の入力欄を追加する |
Filter: 内部ではSiteSettings.GetFilterColumns()がフィルタ列の一覧を返すときに、FieldType == "Filter"の拡張フィールドが追加されます。値はビューのColumnFilterHashに入ります。ViewExtensions: 値はビューのViewExtensionsHashに入ります。コントロール ID は"ViewExtensions__" + フィールド名の形になります。
どちらも SqlParam: true にすると、値が拡張 SQL の @Name パラメータとして渡されます。
図を読み込み中…
設定方法
ファイルで設定する
App_Data/Parameters/ExtendedFields/ に JSON ファイルを置きます。ファイル名は任意(拡張子は .json)で、サブディレクトリで階層管理もできます。
App_Data/
└── Parameters/
└── ExtendedFields/
├── MyFilter.json
└── ViewExt/
└── DateRangeFilter.jsonExtensions テーブルで設定する
Extensions テーブルに ExtensionType = 'Fields' のレコードを追加し、ExtensionSettings 列に設定 JSON を入れる方法もあります。ExtensionName が Name として使われます(ExtensionSettings 内の Name より優先)。ファイルの配布が難しいマルチクラスタ環境などで便利です。
INSERT INTO Extensions (TenantId, ExtensionType, ExtensionName, ExtensionSettings, Description, Disabled)
VALUES (
1,
'Fields',
'Keyword',
'{"FieldType":"Filter","TypeName":"nvarchar","LabelText":"キーワード","SqlParam":true}',
'キーワード横断検索フィルター',
0
);INSERT INTO "Extensions" ("TenantId", "ExtensionType", "ExtensionName", "ExtensionSettings", "Description", "Disabled")
VALUES (
1,
'Fields',
'Keyword',
'{"FieldType":"Filter","TypeName":"nvarchar","LabelText":"キーワード","SqlParam":true}',
'キーワード横断検索フィルター',
false
);INSERT INTO Extensions (TenantId, ExtensionType, ExtensionName, ExtensionSettings, Description, Disabled)
VALUES (
1,
'Fields',
'Keyword',
'{"FieldType":"Filter","TypeName":"nvarchar","LabelText":"キーワード","SqlParam":true}',
'キーワード横断検索フィルター',
0
);WARNING
設定の変更を反映するには、アプリケーションの再起動か、パラメータリロード(/admins/reloadparameters)が必要です(ファイル・Extensions テーブルとも。ExtensionInitializer.cs)。
プロパティ
共通プロパティ(ExtendedBase から継承)
すべての拡張機能に共通するプロパティです。
| プロパティ | 型 | 既定値 | 説明 |
|---|---|---|---|
Name | string | — | フィールド名。SqlParam: true のとき @Name が SQL パラメータ名になる |
Description | string | — | 説明(管理用のメモ) |
Disabled | bool | false | true で無効化 |
SiteIdList | List<long> | null(全サイト) | 適用するサイト ID のリスト |
DeptIdList | List<int> | null(全組織) | 適用する組織 ID のリスト |
GroupIdList | List<int> | null(全グループ) | 適用するグループ ID のリスト |
UserIdList | List<int> | null(全ユーザ) | 適用するユーザ ID のリスト |
IdList | List<long> | null | 適用するレコード ID のリスト |
Controllers | List<string> | null(全コントローラ) | 適用するコントローラ(例: ["items"]。小文字で書く) |
Actions | List<string> | null(全アクション) | 適用するアクション(例: ["index"]。小文字で書く) |
ColumnList | List<string> | null | 列のフィルタ |
INFO
絞り込みのリストが空(null)の場合は「条件なし(すべてに適用)」として扱われます。値の先頭に - を付けると除外指定になります(例: ["-5"] は ID 5 を除外)。
確認したソースでは、拡張フィールドはテーブル(items コントローラ)の画面を開いたときに、ログインユーザ・サイト ID・レコード ID・コントローラ・アクションで絞り込まれます(Context.cs)。コントローラ名・アクション名は小文字で比較されるため(L289-L290)、Controllers はテーブルの種類(Issues など)ではなく items、Actions は index のように小文字で書きます。["Issues"]・["Index"] のように書くと一致しません。
拡張フィールド固有のプロパティ
| プロパティ | 型 | 既定値 | 説明 |
|---|---|---|---|
FieldType | string | — | 表示場所。"Filter" または "ViewExtensions" |
TypeName | string | "nvarchar" | データ型(コントロールの種類に影響する) |
LabelText | string | — | ラベルの文字列 |
ChoicesText | string | — | 選択肢のテキスト(ドロップダウン・ラジオボタン用) |
DefaultInput | string | — | 既定値 |
EditorFormat | string | — | 日時のフォーマット |
ControlType | string | — | コントロールの種類の上書き("TextBox" / "Slider" / "Spinner" など) |
ValidateRequired | bool? | — | 必須の検証 |
ValidateNumber | bool? | — | 数値の検証 |
ValidateDate | bool? | — | 日付の検証 |
ValidateEmail | bool? | — | メール形式の検証 |
MaxLength | decimal? | — | 最大文字数 |
ValidateEqualTo | string | — | 別のフィールドと同じ値かの検証 |
ValidateMaxLength | int? | — | 最大文字数の検証 |
DecimalPlaces | int? | — | 小数点以下の桁数 |
Nullable | bool? | — | null を許可するか |
Unit | string | — | 単位(数値の後ろに表示) |
Min | decimal? | — | 最小値 |
Max | decimal? | — | 最大値 |
Step | decimal? | — | ステップ値 |
AutoPostBack | bool? | — | 値の変更時に自動でポストバックするか |
FieldCss | string | — | フィールド全体の CSS クラス("field-normal" / "field-wide" / "field-auto-thin" など) |
CheckFilterControlType | int | 0 | チェックボックスのフィルタコントロールの種類 |
DateTimeStep | int? | — | 日時のステップ(分単位) |
ControlCss | string | — | コントロール要素の CSS クラス |
After | string | — | 挿入位置。指定した列名の後ろに挿入する |
SqlParam | bool | false | true のとき、値を SQL パラメータ @Name として渡す |
TypeName とコントロールの種類
TypeName によって、画面に表示されるコントロールの種類が決まります。
| TypeName | コントロール | 備考 |
|---|---|---|
nvarchar(既定) | テキストボックス | ChoicesText があればドロップダウン |
int / decimal / float | 数値入力 | ChoicesText があればドロップダウン |
datetime / date | 日時ピッカー | |
bit / bool | チェックボックス |
ChoicesText を設定すると、数値型・文字列型ともにドロップダウンになります。確認したソースでは、拡張フィールドの設定から項目を組み立てるときに ChoicesControlType は引き継がれないため(Context.cs)、ラジオボタンにはできません。ChoicesControlType: "Radio" を指定してもラジオボタンにはなりません。
ChoicesText の書き方
プリザンター標準の項目の選択肢と同じ書式で書きます。
001,営業部
002,開発部
003,管理部標準の項目と同じく、[[Depts]](組織)・[[Groups]](グループ)・[[Users]](ユーザ)などの特殊な書式も使えます(Column.cs)。
[[Depts]][[SQL]] に続けて SELECT 文を書き、DB から選択肢を取得する書式は、1.5.8.1 のソースにはありません。
表示位置(After)
After を指定すると、フィールドを特定の列の後ろに挿入できます。
{
"Name": "MyFilter",
"FieldType": "Filter",
"TypeName": "nvarchar",
"LabelText": "担当部署",
"After": "Status"
}After の状態 | 挿入位置 |
|---|---|
| 列名を指定 | その列の直後(例では Status の直後) |
| 省略または空 | フィルタリストの先頭 |
| 指定した列名が見つからない | リストの末尾 |
ViewExtensions 型で FieldCss を指定しなかった場合は、FieldCss が自動的に "field-auto-thin" になります(Context.cs)。After の有無は関係ありません。
適用範囲の絞り込み
SiteIdList や DeptIdList などで、特定のサイト・ユーザ・組織にだけフィールドを表示できます。
{
"Name": "DivisionFilter",
"FieldType": "Filter",
"TypeName": "nvarchar",
"LabelText": "区分",
"SiteIdList": [100, 200],
"DeptIdList": [10, 20],
"Actions": ["index"]
}この例では、サイト ID が 100 または 200 で、かつ組織 ID が 10 または 20 のユーザが一覧画面(index アクション)を表示したときだけフィールドが表示されます。
SqlParam で拡張 SQL に値を渡す
SqlParam: true にすると、入力値が拡張 SQL の @Name パラメータとして渡されます。拡張 SQL の OnSelectingWhere と、サーバースクリプトの view.OnSelectingWhere を組み合わせると、ユーザが入力した値を WHERE 句に反映できます。仕組みの詳細は view.OnSelectingWhere とフィルター を参照してください。
TIP
SqlParam: true の値は、ビューに値が入っている(ColumnFilterHash / ViewExtensionsHash にキーがある)ときだけ SQL パラメータとして追加されます(View.cs)。値が無いときに @Name を参照する拡張 SQL が実行されると、パラメータ未宣言の SQL エラーになるため、下の例のようにサーバースクリプトで値の有無を確認してから view.OnSelectingWhere を設定します。拡張 SQL の条件式の先頭には AND を付けません(本体が自動で and でつなぎます。拡張 SQL の活用)。
SQL パラメータに渡せるのはスカラー値だけです。複数の値で絞り込みたい場合は、区切り文字列で渡して SQL 側で分割します(複数の値で IN 句フィルタをかける)。
ユースケース
キーワードで複数の列を横断検索する
フィルタエリアに「キーワード」入力欄を追加し、値が入力されているときだけ拡張 SQL で複数の列を横断検索します。
{
"Name": "Keyword",
"FieldType": "Filter",
"TypeName": "nvarchar",
"LabelText": "キーワード",
"SqlParam": true
}{
"Name": "KeywordSearch",
"SpecifyByName": true,
"OnSelectingWhere": true
}SQL ファイル名は App_Data/Parameters/ExtendedSqls/KeywordSearch.json.sql です。
(
"Issues"."ClassA" LIKE '%' + @Keyword + '%'
OR "Issues"."ClassB" LIKE '%' + @Keyword + '%'
OR "Issues"."Body" LIKE '%' + @Keyword + '%'
)(
"Issues"."ClassA" LIKE '%' || @Keyword || '%'
OR "Issues"."ClassB" LIKE '%' || @Keyword || '%'
OR "Issues"."Body" LIKE '%' || @Keyword || '%'
)(
`Issues`.`ClassA` LIKE CONCAT('%', @Keyword, '%')
OR `Issues`.`ClassB` LIKE CONCAT('%', @Keyword, '%')
OR `Issues`.`Body` LIKE CONCAT('%', @Keyword, '%')
)if (!view.Filters.Keyword) return;
view.OnSelectingWhere = "KeywordSearch";固定の選択肢のドロップダウンで絞り込む
{
"Name": "Category",
"FieldType": "Filter",
"TypeName": "nvarchar",
"LabelText": "カテゴリー",
"ChoicesText": "A,製品A\nB,製品B\nC,製品C",
"After": "Status",
"SqlParam": true
}{
"Name": "CategoryFilter",
"SpecifyByName": true,
"OnSelectingWhere": true
}"Issues"."ClassA" = @Categoryif (!view.Filters.Category) return;
view.OnSelectingWhere = "CategoryFilter";DB から取得した選択肢で絞り込む
選択肢を [[Depts]] で組織から作るドロップダウンの例です。値には組織 ID が入ります。拡張 SQL とサーバースクリプトは上の例と同じ形で、パラメータ名だけが変わります。
{
"Name": "DeptCode",
"FieldType": "Filter",
"TypeName": "nvarchar",
"LabelText": "部署",
"ChoicesText": "[[Depts]]",
"SqlParam": true
}{
"Name": "DeptFilter",
"SpecifyByName": true,
"OnSelectingWhere": true
}"Issues"."ClassB" = @DeptCodeif (!view.Filters.DeptCode) return;
view.OnSelectingWhere = "DeptFilter";ビュー拡張エリアに日付入力欄を置く
ViewExtensions 型で「基準日」の日付ピッカーをビュー拡張エリアに置く例です。
{
"Name": "BaseDate",
"FieldType": "ViewExtensions",
"TypeName": "datetime",
"LabelText": "基準日",
"EditorFormat": "Ymd",
"DefaultInput": "today",
"SqlParam": true
}サーバースクリプトで view.ViewExtensions.BaseDate を確認してから view.OnSelectingWhere で絞り込む拡張 SQL を適用する方法は、1.5.8.1 のソースでは使えません。
- サーバースクリプトの
viewにはFilters(ColumnFilterHashの値)はありますが、ViewExtensionsはありません(ServerScriptModelView.cs、ServerScriptModel.cs)。view.ViewExtensions.BaseDateは未定義のプロパティを読むことになり、エラーになります。 - ビュー拡張エリアの値は画面で入力したときにだけ
ViewExtensionsHashに入り、DefaultInputを設定しただけでは入りません(View.cs)。値が無いときに@BaseDateを参照する SQL が実行されると、パラメータ未宣言のエラーになります。 ViewExtensionsHashのキーの有無で適用を切り替えられるのは、OnSelectingColumn用のOnSelectingColumnParamsです(Rds.cs)。OnSelectingWhere用のOnSelectingWhereParamsはフィルタ(ColumnFilterHash)のキーしか見ません(L6190-L6192)。
ビュー拡張エリアの値で一覧を絞り込む方法は、ソースからは確認できませんでした。値で列の表示内容を変えたい場合は、OnSelectingColumn と OnSelectingColumnParams: ["BaseDate"] を組み合わせます。
特定のサイト・ユーザにだけ表示する
SiteIdList でサイトを、UserIdList でユーザを限定します。この例では、サイト 123 でユーザ ID 1・2 のユーザにだけフィルタ欄が表示され、それ以外のユーザには表示されません。
{
"Name": "InternalCode",
"FieldType": "Filter",
"TypeName": "nvarchar",
"LabelText": "内部コード(管理者専用)",
"SiteIdList": [123],
"UserIdList": [1, 2],
"SqlParam": true
}数値をスライダーで入力する
ControlType: "Slider" で数値入力をスライダーにします。
{
"Name": "PriorityMin",
"FieldType": "Filter",
"TypeName": "decimal",
"LabelText": "優先度(最低)",
"ControlType": "Slider",
"Min": 0,
"Max": 100,
"Step": 10,
"DefaultInput": "0",
"SqlParam": true
}"Issues"."NumA" >= @PriorityMinまとめ
| 項目 | 内容 |
|---|---|
FieldType: "Filter" | 一覧のフィルタエリアにフィールドを追加する |
FieldType: "ViewExtensions" | ビュー拡張エリアにフィールドを追加する |
TypeName | データ型でコントロールの種類を決める(nvarchar / datetime / int / bit など) |
ChoicesText | ドロップダウンの選択肢を設定する([[SQL]] で DB 参照も可) |
After | 特定の列の後ろに挿入する |
SiteIdList など | 表示するサイト・ユーザ・組織を絞り込む |
SqlParam: true | 入力値を拡張 SQL の @Name パラメータとして渡す |