[OutSystems]Associate Reactive Developerのサンプル問題について解説 2/4(#6-#10)

Associateは入門レベルの試験で、この試験の合格が他の試験の受験資格にもなっています。
Reactiveとついている通り、Reactive Web App開発の基礎的な知識を問われる試験。

試験問題は、
https://www.outsystems.com/learn/certifications/
の、「Associate Reactive Developer (OutSystems 11)」項目のリンク「Exam Details」でダウンロードできる資料から。解凍したら、Japaneseフォルダにあるファイル「Associate Reactive Developer Sample Exam - JP.pdf」を開いてください。

[Associate Reactive Developerのサンプル問題について解説 1/4(#1-#5)](https://qiita.com/jyunji_watanabe/items/b9c88df3c5a97853ae5f)
Associate Reactive Developerのサンプル問題について解説 2/4(#6-#10)
[Associate Reactive Developerのサンプル問題について解説 3/4(#11-#15)](https://qiita.com/jyunji_watanabe/items/4452e8cabab795726cb0)
[Associate Reactive Developerのサンプル問題について解説 4/4(#16-#20)](https://qiita.com/jyunji_watanabe/items/1c7d603b5e66d0aa305a)

#6 ブロックとイベント（OnInitialize）
Reactive Web Appとモバイルアプリでは、画面で自動発生し、Service Studioでハンドラをかけるイベントがいくつかあり、Initializeはその1つです。

画面遷移を行うときに最初に発生するイベントがInitializeで、そのハンドラでは変数の初期化などを行います。Initializeが終了してから画面に定義されたAggregateとData Actionが開始されます（FetchプロパティがAt Startの場合）。
DOMが完全に準備されると、Readyイベントが発生します。つまり、Initializeの時点ではDOMは準備できていません。

というわけで、選択肢A（On Initializeイベントは、画面やブロックの描画前、かつデータの取得開始前にトリガーされる。）が正解。

他の選択肢を見ておきます。
B：「画面やブロックの描画後にトリガーされる」のはRender。画面のDOMが準備された後、最初の1回の描画時のみにトリガーされるのはReady。いずれにせよInitializeとは違います
C：「Aggregateによるデータの取得後にトリガーされ」るのは、After Fetch。AggregateのOn After Fetchプロパティでハンドラを設定できます
D：「ブロックの入力パラメータの変更後にトリガーされる」のはParameter Changed。Blockを配置した画面側から、Blockの入力パラメータを変更すると発生します

イベントのライフサイクルについて詳しくは、[画面とブロックのライフサイクルイベント](https://success.outsystems.com/ja-jp/Documentation/11/Developing_an_Application/Implement_Application_Logic/Screen_and_Block_Lifecycle_Events)を参照。

#7 Aggregate/画面でのデータ取得（FetchプロパティとOn After Fetch）
まず、前提知識を整理しておきます。

## Fetchプロパティ
画面に定義したAggregateのFetchプロパティは、以下の2つの値のいずれかをとります。
At start：Initializeイベント終了後、自動的にデータ取得が開始される
Only on demand：Action FlowでRefresh Dataしたときのみデータの取得が開始される

## On After Fetch
Aggregateのデータ取得が終了すると発生するイベントがAfter Fetch。
AggregateのプロパティOn After Fetchでそのハンドラを定義できます。

よくある使い方は、複数のAggregateの実行に順序を付けたいときに、1つ目のAggreagteのOn After Fetchでフィルタ条件を変更した上で、2つ目のAggregateに対しRefresh Dataするというもの。

## 問題の検討
問題の設定から

- CountryというEntityから国の一覧をDropdown Widgetに表示する
- CityというEntityから都市の一覧をDropdown Widgetに表示する
- ただし、CityのDropdownに表示するのは、選択した国内の都市のみにする

というのが実現したいこと。
これを実現するためには、Countryで国を選択したときに、Cityを検索するAggregateを新しい条件で再検索し、その結果を2番めのDropdownに表示する必要があります。

各選択肢を検討してみましょう。設問は「正しくないもの」です。
A：○。これは必須ではないと思いますが、×ではないですね。初期表示のやり方として、①Local変数Cityにデフォルト値を設定しておいて、GetCitiesのFetchはAt startにする②FetchはOnly on demandにして、CountryのDropdownは未選択で初期表示する、の2通り考えられます。この選択肢は②の方針かと思われます
B：○。CountryのDropdownの選択が変わるとOnChange Screen Actionが動きます。国が変わったので、都市を検索する条件が変わってます。よってGetCities Aggregateを更新してデータを再取得する
C：○。選択された国内の都市を検索したいわけなので、都市を検索するAggregateのFilterに条件を設定します。
D：×。都市の再取得（GetCities Aggregate）は、対象の国が変わったときです。国のAggregateを取得したときではありません。
というわけで正解はD。

#8 ブロックとイベント（ブロック）
ブロックは一塊のUI要素と、そのためのデータ取得及びロジックを部品としてラッピングし、各画面に配置して利用できるようにするもの。

正解は選択肢B（画面や他のブロックでインスタンス化できる）。
ブロックは独立して配置することはできません。必ず画面か他のブロックに配置して利用します。
A：×。ブロックにも配置できる。
C：×。画面かブロックに配置する必要があり、クライアントアクションだけで表示させることはできません。
D：×。「外部HTMLでもインスタンス化」というのはOutSystemsの仕組みを通さずに表示できるという意味でしょうが、そういうことはできません。

#9 ブロックとイベント（Trigger Event）
ブロックにはEventという要素を追加できます。
画面と配置したブロックの間には、仕組み上の壁があり、画面は自由にブロック内を操作することができません。
ブロックで特定のタイミング（通信の終了や、UIの準備完了など）に名前をつけ、配置した画面側でこのタイミングに反応するActionを書くことができます。
この仕組がブロックのEventです。Eventのハンドラを作れば、画面はブロック内で発生したデータを受け取って操作することもできます（画面から直接ブロック内のローカル変数を操作することはできない）。

詳しくは[イベントを使用してブロックの変更を親に反映する](https://success.outsystems.com/ja-jp/Documentation/11/Developing_an_Application/Design_UI/Reuse_UI/Use_Events_to_Propagate_Changes_From_a_Block_to_the_Parent)を参照。

この問題で聞かれているTrigger Eventというのは、定義したEventを発生させる要素で、ブロックのAction Flowに記述します。各選択肢では、イベントが発生したかをどこからどこへ通知するか、というのがポイント。
イベントは、「イベントを定義したブロック」から「ブロックを配置した親の画面・ブロック」へ通知するものです。

この説明に合致する選択肢は、A（Trigger Eventを使用すると、ブロックからその親（画面またはブロック）に、ブロックのスコープ内で関連イベントが発生したことを通知できる。）です。

#10 フォームの検証（Built-in Validation）
詳細な情報は[フォームのフィールドを検証する](https://success.outsystems.com/ja-jp/Documentation/11/Developing_an_Application/Design_UI/Forms/Validate_the_fields_of_a_form)参照。

ButtonのBuilt-in Validations（Eventsカテゴリにある）をYesに設定しておくと、Clickイベント時に、Form内のInputの入力をチェックしてくれます。
対象は、

- 必須なのに入力がない項目がないか（Mandatoryプロパティで指定：入力必須であることを示す）
- 型が一致しない入力がされた項目がないか（ドキュメントでは、Input Typeプロパティを見ているようなことが書いてあるが、動かしてみるとむしろFormのSourceに紐付けているEntity属性の型をチェックしているように見える）

Built-in Validationsの結果は、以下のように設定される。

- 各入力WidgetのValidプロパティにValidationの結果（Falseだとエラーあり）
- 各入力WidgetのValidationMessageにエラーメッセージ（エラーがなければ空）
- Form WidgetのValueプロパティにはForm全体での検証結果（1つでも入力項目にエラーがあればFalseになる）

デバッガを使って、わざとBuilt-in Validationに引っかかる入力を渡したときのWidgetの値。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/3ff00cf3-44fa-0992-87ae-23f1f4bdb841.png)

以上を踏まえて、各選択肢を見ていきます。
A：×。型もチェックされる
B：×。「ロジックで使用される」という限定はない。Form内の全項目がチェックされる
C、D：保留。どちらの選択肢も、前半は必須フィールドが入力されているか、ということを言っていて正しい。後半のチェック対象が、Cは入力フィールドの想定データ型（Input TYpeプロパティのことであろう）であり、DはFormのソースのデータ型となっているところに違いがある。サンプル問題に示された正解はCであり、ドキュメントでもCのほうが正しい。ただし、実際に動作させてみると疑問はある。Input Typeでは数値項目に「Number」を指定するのだが、上に示したデバッガのSS（Input_Int WidgetはデータソースがInteger型で、Input TypeはNumberとしている）のようにエラーメッセージは「Enter a valid integer.」となっており、むしろデータソースの型の方を見ていることを示唆している。

というわけで、A/Bは確実に落とせるのですが、CかDかは悩む。試験時に回答するならドキュメントに記載のあるCの方でしょうか……。
ここは後で修正するかもしれません。