カスタム関数の活用
Validate関数の検証ルールに、自作の関数を指定することもできます。
以下は、メールアドレスの形式をチェックするカスタム関数の例です。
Set(IsValidEmail,
Function(email,
IsMatch(
email,
"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
)
)
);
TextInput1.HintText = Validate(IsValidEmail(TextInput1.Text), "正しいメールアドレスを入力してください")
- IsValidEmail関数は、引数のemailが正規表現パターンにマッチするかどうかを判定し、true/falseを返します。
- メールアドレスの正規表現パターンは複雑なので、Validate関数の中に直接記述するのは避けた方が良いでしょう。
- カスタム関数に切り出すことで、コードの可読性とメンテナンス性が向上します。
入力値の変換と検証
Validate関数の第3引数を活用すると、検証エラーがない場合に入力値を変換することもできます。
以下は、テキストボックスに入力された数値を整数に変換する例です。
TextInput1.Text = Validate(IsNumeric(TextInput1.Text), TextInput1.Text, Value(TextInput1.Text))
- 検証ルールのIsNumeric関数は、入力値が数値として解釈可能かどうかを判定します。
- 第3引数のValue関数は、入力値を数値型に変換します。
- 検証エラーがない場合は、変換された整数値がテキストボックスに設定されます。
動的なバリデーションルール
状況に応じて検証ルールを動的に切り替えることで、より柔軟な入力チェックが可能になります。
以下は、チェックボックスの状態に応じて必須入力を制御する例です。
TextInput1.HintText = Validate(CheckBox1.Value = false || Not(IsBlank(TextInput1.Text)), "必須項目です")
- CheckBox1.Valueがfalse(未チェック)の場合は、TextInput1が空欄でも検証エラーにはなりません。
- CheckBox1.Valueがtrue(チェック済み)の場合は、TextInput1が必須入力項目になります。
- このように、他のコントロールの状態を検証ルールに組み込むことで、動的な入力チェックを実現できます。
コレクションを使った検証
PowerAppsのコレクションを使えば、マスターデータと照合した入力チェックも可能です。
以下は、社員IDの入力値が社員マスターに存在するかどうかを検証する例です。
ClearCollect(EmployeeList,
Table(
{ID: "EMP001", Name: "山田太郎"},
{ID: "EMP002", Name: "鈴木花子"},
{ID: "EMP003", Name: "佐藤次郎"}
)
);
TextInput1.HintText = Validate(IsBlank(LookUp(EmployeeList, ID = TextInput1.Text)), "社員IDが見つかりません")
- EmployeeListコレクションには、社員IDと社員名の対応関係が格納されています。
- 検証ルールでは、LookUp関数を使って入力されたIDがEmployeeListコレクションに存在するかどうかを判定しています。
- 該当するレコードが見つからない場合は、"社員IDが見つかりません"というエラーメッセージが表示されます。
社員マスターだけでなく、取引先マスターや商品マスターなど、さまざまなマスターデータとの連携が考えられます。
データソースとしてはコレクションの他にも、ExcelファイルやSQLデータベースなどを利用できます。
非同期バリデーション
ここまでの例は、いずれもクライアント側で完結するバリデーションでした。
一方、サーバー側のデータを参照する必要があるケースでは、非同期処理を利用する必要があります。
以下は、サーバー上のユーザーマスターと照合して、ユーザーIDの重複をチェックする例です。
Set(CheckUserID,
Function(userID,
Filter(
'User Master',
ID = userID
)
)
);
If(
IsBlank(TextInput1.Text),
Set(isDuplicateID, false),
ClearCollect(
DuplicateIDList,
CheckUserID(TextInput1.Text)
);
Set(isDuplicateID, CountRows(DuplicateIDList) > 0)
);
TextInput1.HintText = Validate(Not(isDuplicateID), "このIDは既に使用されています", TextInput1.Text)
- CheckUserID関数は、引数のuserIDに一致するレコードをUser Masterテーブルから抽出します。
- IDが入力されていない場合は、isDuplicateID変数にfalseを設定します。
- IDが入力されている場合は、CheckUserID関数を呼び出し、結果をDuplicateIDListコレクションに格納します。
- DuplicateIDListの件数が0より大きい場合は、isDuplicateID変数にtrueを設定します。
- 最後に、isDuplicateIDの値に応じてValidate関数でエラーメッセージを表示します。
このように、サーバー側のデータ取得には非同期処理が必要になるため、手順が少し複雑になります。
フラグ変数を使ってデータ取得の完了を待ち合わせるのがポイントですね。
より実践的なアプリケーションでは、レスポンスが返ってくるまでの間にインジケーターを表示するなど、ユーザビリティにも配慮が必要でしょう。
エラーメッセージの多言語化
アプリのグローバル展開を見据えている場合は、エラーメッセージの多言語化も検討したいところです。
PowerAppsでは、リソースファイルを使って文字列を一元管理することができます。
以下は、言語に応じてエラーメッセージを切り替える例です。
TextInput1.HintText = Validate(Not(IsBlank(TextInput1.Text)), LookUp(ErrorMessage, Key = "E001").Message)
- ErrorMessageテーブルには、エラーコードとエラーメッセージの対応関係が言語別に格納されているものとします。
- LookUp関数で言語に対応するエラーメッセージを取得し、Validate関数の第2引数に指定します。
- アプリの言語設定を変更することで、エラーメッセージも連動して切り替わります。
言語切替時の動的なメッセージ変更も、Validateのメリットの1つと言えるでしょう。
エラーコードとメッセージを分離することで、メンテナンス性も向上します。