Oracle® Fusion Middleware Oracle Business Process Composerによるビジネス・プロセスの開発 12c (12.2.1.1) E77375-01 |
|
前へ |
次へ |
この付録では、WebフォームでWebフォーム・ルールを使用するための例とユース・ケースを提供します。フォーム・ルールの全般情報は、「Webフォーム・ルールの使用」を参照してください。
この付録の内容は次のとおりです。
次の例では、3つのコントロールを持つフォームがあり、それぞれにN1、N2、Tという名前が割り当てられていると仮定します。ユーザーがN1またはN2に値を入力したとき、Tの値をN1とN2の合計に設定するとします。
このルールは次のように記述できます:
if (N1.value > 0 || N2.value > 0) { T.value = N1.value + N2.value; }
このルールは、N1またはN2に値を入力すると自動的にその値をTに設定します。式には、減算や乗算など有効なJavaScript演算子を使用できます。ただし、計算された値は必ずTのタイプのコンテキストで有効であることが重要です。たとえばTのタイプが整数で、式の計算値が少数(1.5など)の場合、このルールはTに無効な値を設定しようとすることになります。これによりエラーが生成されます。このルールで指定された値は設定されますが、フィールドは無効とマークされ、送信ボタンを無効にしたりコントロールの背景を赤で表示したりするなど適切なアクションが実行されます。
また、パレットからフォームにコントロールを追加する場合は、タイプが適切かどうかを確認することが重要です。たとえば、前述したような数値計算の場合、コントロールのタイプは数値である必要があります。
次の例では、2つのコントロールを持つフォームがあり、それぞれにBおよびSという名前が割り当てられていると仮定します。Bはチェック・ボックスで、1つのオプションがあり、その値はYesです。Sに別の請求先住所を入力したいとユーザーがチェックした場合、Sが表示されます。
フォーム・ルールは次のように記述されます。
if (B[0].value == 'Yes') { S.visible = true; } else { S.visible = false; }
このフォーム・ルールは、ユーザーがBのチェック・ボックスを選択または解除すると自動的に実行され、請求先住所セクションSの表示と非表示を切り替えます。ブール値のtrueまたはfalse値に評価されるものであれば、Sの表示プロパティを計算する任意の有効なJavaScript式を使用できます。この例では、チェック・ボックスBのデフォルトを選択解除の状態にし、セクションSのデフォルトを非表示にするのが一般的です。
次の例では、フォームにFacilityという名前のラジオ・コントロールがあり、選択したオプションに応じてメッセージを表示します。
if (Facility.value == 'Boston' || CompanyFacility.value == 'New York') { Msg.visible = true; } else { Msg.visible = false; }
この例では、2つのコントロールを持つフォームがあり、それぞれにBおよびQという名前が割り当てられていると仮定します。Bはチェック・ボックスで、1つのオプションがあり、その値はYesです。チェック・ボックスを選択したユーザーは喫煙者であり、Qで追加質問がたずねられます。
このルールは次のように記述できます:
if (B[0].value == 'Yes') { Q.enabled = true; } else { Q.enabled = false; }
このルールは、ユーザーがBのチェック・ボックスを選択または選択解除すると自動的に実行され、Qの質問の有効/無効を切り替えます。ここでも、ブール値のtrueまたはfalse値に評価されるものであれば、Qの有効なプロパティを計算する任意の有効なJavaScript式を使用できます。
この例では、チェック・ボックスBのデフォルトを選択解除の状態にし、コントロールQのデフォルトを無効にするのが一般的です。
次のフォーム・ルールは、繰返しアイテムを処理する例です。たとえば、ユーザーが購入できるアイテムを表す繰返しセクションのあるフォームがあります。各セクションは、価格(名前はP)、数量(名前はQ)、そして小計(名前はS)です。ページ上には複数のアイテムがあり、ページごとのアイテムの数は不明です。価格フィールドは、自動的に入力されます。いずれかのアイテムの数量フィールドに値を入力して、小計を計算します。
このルールは次のように記述されます:
for (var i = 0; i < S.value.length; i++) { if (Q[i].value > 0) { S[i].value = Q[i].value * P[i].value; } else { S[i].value = 0; } }
このルールは、いずれかのアイテムの数量フィールドにユーザーが値を入力すると常に自動的に実行されます。数量が0より大きい各アイテムの小計が計算され、そのアイテムの小計フィールドに計算された値が入力されます。特定のアイテムに数量がない場合、小計は計算されません。
次のフォーム・ルールは、繰返しアイテムを処理する例です。ここでは、Tという名前で合計のコントロールがあると仮定します。合計の値を、前述の小計をすべて計算した合計の請求金額に設定するとします。
このルールは、次のように記述されます。
var tot = 0; for (var i = 0; i < S.value.length; i++) { tot = tot + S[i].value; } T.value = tot;
このルールは、前述のルールによって更新されたときなど小計が更新されるたびに実行されます。請求合計に到達するまですべての小計の値が加算されます。合計の計算には、一時変数を使用する必要があります。
このルールを次のように記述します:
T.value = 0; for (var i = 0; i < S.value.length; i++) { T.value = T.value + S[i].value; }
これは正常に動作しません。これは、ルールの評価に関する内部制限が理由です。このルールは繰返しコントロールの内部のコントロールで動作しています。繰返しコントロールがExpenseRepeatという名前であると想定した場合、アイテムを繰返しから削除するように処理するには、次のように追加する必要があります。表コントロールは、レイアウトの異なる繰返しです。表コントロールにも同じことが適用されます。表の名前がExpenseである場合、繰返しは自動的にExpenseRepeatという名前になります。
if (ExpenseRepeat.itemRemoved) {;}
このフォーム例では、Descという名前のテキスト領域コントロールがあり、そこにユーザーが最大500文字までの説明を入力できます。HTMLでは、テキスト領域コントロールのmaxLengthを設定する方法はありません。この制限のため、テキスト領域コントロールには、テキスト・コントロールのようなmaxlengthプロパティがありません。
フォーム・ルールを使用すればこれを実現できます。このコントロールで、ErrorMsgプロパティに「You must limit your description to 500 characters」という文字列も設定します。次のビジネス・ルールによって説明コントロールが無効に設定されると、このメッセージが自動的に表示されます。
if (Desc.value.length > 500) { Desc.valid = false; } else { Desc.valid = true; }
エラー・メッセージをカスタマイズするには、次の行をルールに追加します。
Desc.status = 'Invalid. Max 20 chars allowed and you have ' + Desc.value.length;
ユーザーに許可される最大を超える文字数を示すエラー・メッセージです。
テキスト領域コントロールには、複数行のテキストを入力するのが普通です。WebページやHTML形式の電子メールなどのHTMLコンテキスト、またはフォームのフォーム・アクション表示メッセージでそのテキストを表示する場合は、改行文字をHTMLブレークに置き換える必要があります。これは改行の違いが原因で、Webフォームのテキスト領域に入力される改行は1つの改行文字\nで表されますが、HTMLコンテキストでの改行はHTMLブレーク文字で表されます。
次の例では、Descriptionという名前のテキスト領域コントロールと、DFという名前の非表示のコントロールがあります。表示されているDescriptionというコントロールにユーザーがテキストを入力すると、ビジネス・ルールによって改行文字\nがHTMLブレーク文字に変換されます。
var x = Description.value; x = x.replace(/\\n/g,"<br/>"); DF.value = x;
次の例では、1つのドロップダウンで選択されるオプションを、別で選択したオプションに基づいて自動的に設定します。これは、動的に移入される選択肢を持つフォームが存在する場合に便利です。
たとえば、製品選択が説明的なテキストである場合を考えます。ユーザーが製品を選択したとき、説明的な製品テキストではなく製品IDに基づいてアクションを実行するフォームである必要があります。これは、製品選択ドロップダウンを動的に移入するルールによって、フォームの非表示のままの製品IDドロップダウンもまた移入されるようにすると簡単です。製品の選択肢のドロップダウン・コントロールはPという名前で、製品IDのドロップダウン・コントロールはIDという名前です。
1番目のルール「Load Products」で、表示されるドロップダウンと非表示のドロップダウンの両方に、データベースからのオプションが移入されます。
Load Products: -------------- if (form.load) { eval('x=' + http.get('http://localhost:8082/database/products')); var opts1 = []; var opts2 = []; for (var i=0; i < x.resultSet.length; i++) { if (x.resultSet[i]) { opts1[i] = x.resultSet[i].description; opts2[i] = x.resultSet[i].productId; } } Products.options = opts1; PID.options = opts2; Products.value = opts1[0]; // default to 1st product option PID.value = opts2[0]; }
2番目のルールSelect Product IDは、非表示のPIDドロップダウンと、表示されている製品説明のドロップダウンとの同期を保ちます。
Select Product ID Rule: ----------------------- if (Products.value.length > 0) { var i; for (x in Products.options) { if (Products.value == Products.options[x]) i = Products.options.indexOf(Products.options[x]); } PID.value = PID.options[i] + ''; }
v4のルールで非表示のドロップダウンを使用して説明オプションのラベルを表示する一方で、暗号化されたデータベース値を非表示のままにするのは多くの場合不要になります。ドロップダウンのオプションは、ユーザーに見えるオプション・ラベルとは別の値を持ちます。上記は単一の簡単なルールで実行することが可能です。
for (var i=0; i < x.resultSet.length; i++) { if (x.resultSet[i]) { opts1[i] = x.resultSet[i].productId+ '=' + x.resultSet[i].description; } } Rdocnum.options = opts1;
製品選択と製品IDドロップダウン両方に動的に移入するルールをもう1つ示します。このルールは、上で示されているデータベース・コネクタによって返される結果セットではなくオブジェクトを返すRESTというサービスを呼び出します。詳細は、動的コンテンツに関する項を参照してください。
if (S.value.length > 0) { eval('x=' + http.get('http://localhost:8182/products/?category=' + S.value)); P.options = x.products; ID.options = x.ids; }
前述の製品検索の例は、多くの場合、非表示の選択コントロールと組み合せて使用されます。
データベース表に製品のリストがあると仮定します。製品ごとに、製品の説明と一意の製品IDがあります。ユーザーは、フォーム上のドロップダウンから製品を選択する必要があります。ドロップダウンには、製品の説明を移入します。ユーザーは製品IDを知らなくてもかまいませんが、他を選択するために、データベースに対するキーとしてIDを使用する必要があります。これを行うには非表示のドロップダウンを別のフォームに追加し、IDを移入します。この例には、Productsという名前で表示されるドロップダウンと、PIDという名前の非表示のドロップダウンがあります。データベースから動的にこれらのドロップダウンに移入する前述のルールを参照してください。
このルールは、選択するPIDオプションと、選択する製品との同期を保ちます。
var i; for (x in Products.options) { // Determine the index of the selected product in the Products dropdown options if (Products.value == Products.options[x]) i = Products.options.indexOf(Products.options[x]); } // Changed the selected PID to match the selected Product PID.value = PID.options[i] + '';
このサンプルは、ドロップダウン・オプションを自動的に追加される空白のオプションにリセットします。
パレット・コントロールおよびスキーマから追加するドロップダウンの場合は、Oracle Web Formsによって自動的に空白のオプションが追加されるので、デフォルトでは始めはドロップダウンに何の選択も表示されません。ドロップダウンをリセットするには、ドロップダウン・コントロールの値を空の文字列ではなくnullに設定します。空の文字列は有効なオプションではないため、空の文字列は機能しません。このフォームは、製品オプションの値が変更されるたびに、サイズという名前のドロップダウンをリセットします。
if (product.value.length > 0) { size.value = null; }
次に示すように、ビジネス・ルールでオプションが動的に設定される場合、フォーム・デザイナ上でデフォルトを設定することはできません。デフォルトはルールで設定する必要があります。
オプションに<value>=<label>があって、valueがlabelと異なる場合には、<label>でも<value>=<label>でもなく、<value>に<control>.valueを設定してください。
if (form.load) { var cc = ['R=Red', 'B=Blue', 'G=Green']; Colors.options = cc; Colors.value = 'B'; }
チェック・ボックス・コントロールがOracle Web Formsの他のパレットと異なるのは、複数選択できるという点です。したがって、チェック・ボックス・コントロールを使用するルールを作成する方法は、多くの点が繰返しコントロールを使用するルールと似ています。
このルールには、colorPaletteという名前のチェック・ボックス・コントロールがあり、オプションはpurple、green、blue、yellow、orangeの各色です。フォームには、colorChoiceという名前のテキスト・コントロールもあります。このルールは、colorPaletteから選択した選択肢をcolorChoiceに割り当てます。
var choices = ''; for (var i = 0; i < colorPalette.value.length; i++) { choices = choices + colorPalette[i].value; } colorChoice.value = choices;
繰返しコントロールと同じように、内部評価制限があるため、forループ内部の変数でオプションを取得する必要があります。その後、そのコントロールのName.valueをforループの外側の変数に割り当てます。
このルールは、チェック・ボックス・コントロールが配列型であることを示すもう1つの例です。
if (colorPalette.value.length > 0) { colorChoice.value = 'Thank you for choosing colors'; } else { colorChoice.value = 'Please choose colors...'; }
このルールは、ユーザーが選択したチェック・ボックスの選択肢に基づいてコントロールの表示/非表示を切り替えます。
このフォームには、Structuresという名前の複数選択チェック・ボックスがあります。ユーザーが「Detached Garage」または「House」オプションを選択した場合に、Detailsという名前のテキスト・フィールドを表示します。
ここでも同様に、チェック・ボックスは複数選択なので、配列として扱われます。配列には選択した(チェックした)すべてのオプションが含まれます。
チェック・ボックスをパレットから追加する際に、オプションが空白を含む複数の単語である場合、オプションの配列で空白文字が'_'の文字に変換されます。次のように比較する必要があります。スキーマからのチェック・ボックス・コントロールは、空白が'_'に置換されません。
var found = false; for (var i = 0; i < Structures.value.length; i++) { if (Structures[i].value == 'Detached_Garage' || Structures[i].value == 'House') { found = true; break; } } if (found == true) { Details.visible = true; } else { Details.visible = false; Details.value = null; }
Detailsを非表示にするときはその値もクリアします。これは、ユーザーがStructuresチェック・ボックスでDetailsを表示するオプションのいずれかを選択しており、かつDetailsに値を入力した可能性があるからです。そして、ユーザーが考えを変え、Detailsを表示するオプションの選択を解除した可能性があるからです。Detailsに入力された値をフォーム送信時に含めたくない場合には、それを非表示にするときに値をクリアします。
チェック・ボックスのオプションは複数選択できるので、ルールを介して複数オプションを選択するには、次の構文を使用する必要があります。
この例ではCBという名前のチェック・ボックス・コントロールがあり、そのオプションがred、green、blueです。このルールは、オプションをすべて選択します。
CB.value = ['red', 'green', 'blue'];
CBという名前のコントロールで、チェックされたオプションをすべてクリアするには:
CB.value = [];
この例のルールは、ユーザーが選択したチェック・ボックスのラベルを表示します。
var selectedcolors = ''; for (var i = 0; i < RGB.value.length; i++) { var v = RGB[i].value; for (x in RGB.options) { var opt = RGB.options[x]; var val= opt.split('=')[0]; var lab= opt.split('=')[1]; if (v == val) { selectedcolors = selectedcolors + ' ' + lab; } } }
コントロールの内部のチェック・ボックスは、他の配列(繰返しチェック・ボックス・コントロール自体)の内部にあるチェック・ボックス・オプション値の配列(各チェック・ボックス・コントロールの値)として扱う必要があります。
このフォーム例では、繰返しセクションに2つのコントロールがあります。テキスト・コントロールであるMessageと、1つのオプション'yes'を持つチェック・ボックス・コントロールであるAreYouAttendingです。選択したオプションにアクセスする構文は、次のとおりです:
AreYouAttending[i].value[0] == 'yes'
for (var i = 0; i < AreYouAttending.value.length; i++) { if (AreYouAttending[i].value[0] == 'yes') { Message[i].value = Name.value + ' is attending event #' + i; } }
繰返しコントロールの内部にメッセージ・コントロールを配置する場合は、ユーザーがクリックして新しい繰返しアイテムを追加したときにメッセージを繰返すルールをメッセージ・コントロールに追加する必要があります。
次の例で、1番目のアイテムではメッセージが正しく表示されますが、ユーザーが追加した2番目、3番目、それ以降のアイテムを表示するにはルールが必要です。
この場合、1番目のメッセージ・コントロールにある動的テキスト(Contest Nomination For: [Name])と、2番目のメッセージ・コントロールにある静的テキスト(By signing this consent form...)の両方をルールによって繰り返します。
if (Consent.itemAdded) { var index = Consent.itemIndex; ConsentNominationForMsg[index].value = 'Contest Nomination For: ' + ClubName.value + ' by ' + NominatorSName.value; ConsentMsg[index].value = 'By signing this consent form you hereby agree that it is acceptable to use a photo or video with your image.'; }
ビジネス・ルールでメッセージ・コントロールを使用して、それより前のフォーム・フィールドで入力された値から、フォーム上のサマリー情報を作成することができます。
このルールでは、JavaScriptの変数を使用してフォーム・フィールドの値とテキスト文字列、およびサマリー・ページを見やすくするHTMLを連結しています。
var totalAssets = TotalAutoValue.value + TotalBankValue.value + TotalRealEstateValue.value; BasicSummaryMsg.value = "<b>Name:</b> " + FirstName.value + " " + LastName.value + "<br/>" + "<b>Phone:</b> " + Phone.value + "<br/>" + "<b>Email:</b> " + EmailAddress.value; if (MilitaryOrCivilian.value == 'Military') { //Military DetailedSummaryMsg.value = "<b>Military Info:</b><br/>" + "Military ID: " + MilitaryID.value + "<br/>" + "Rank: " + Rank.value + "<br/>" + "CurrentTitle: " + CurrentTitle.value + "<br/>" + "Years of Service: " + YearsOfService.value + "<br/>"; } else if (MilitaryOrCivilian.value == 'Civilian') { //Civilian DetailedSummaryMsg.value = "<b>Civilian Info:</b><br/>" + "SSN: " + SSN.value + "<br/>" + "Current Employer: " + CurrentEmployer.value + "<br/>" + "Current Title: " + CurrentTitle2.value + "<br/>" + "Start Date: " + StartDate.value + "<br/>"; } FinancialSummaryMsg.value = "<b>Total Assets:</b> $" + totalAssets + "<br/>" + "Total Bank Assets: $" + TotalBankValue.value + "<br/>" + "Total Real Estate Value: $" + TotalRealEstateValue.value + "<br/>" + "Total Auto Value: $" + TotalAutoValue.value + "<br/>";
繰返しコントロールのフィールド値を使用する場合は、JavaScriptのvarを使用して連結結果をvarに割り当て、さらにそのvarをOracle Web Formsメッセージ・コントロール値に割り当てる必要があります。たとえば、Summaryという名前のメッセージ・コントロールと、Accountという名前の繰返しコントロールがあるとします:
var acctSummary; for (var i = 0; i < Account.value.length; i++) { if (Q[i].value > 0) { acctSummary = acctSummary + 'Account #' + i + ': ' + Account[i].value + '<br/>'; } } Summary.value = acctSummary;
このルールは、ユーザーがnickName入力テキスト・コントロールに値を入力したときにメッセージ・コントロールnickNameThankYouを表示し、ユーザーがnickNameの値を削除したときにメッセージ・コントロールを非表示にします。
if (nickName.value.length > 0 ) { nickNameThankYou.visible = true; } else { nickNameThankYou.visible = false; }
多くの場合、セクション・コントロールには多くの内部コントロールがあります。たとえば、患者の病歴を記入するフォームがあるとします。このフォームには、患者が補聴器を使用しているかどうかを確認する質問があります。答えがYesの場合は、補聴器の使用状況についての詳細(左耳のみ、右耳のみ、両耳、補聴器のブランドなど)をさらに収集する必要があります。答えがNoの場合は、補聴器に関する質問をすべて非表示にします。また、答えがYesの場合は補聴器に関するすべての質問に答えてもらう必要があります。
非表示にしたい他のコントロールを含むセクションの内部で、メッセージ・コントロールは使用しないようにしてください。メッセージ・コントロールには常に値が含まれるため、セクション、またはセクション内の他のコントロールが必須になり、フォームの送信ボタンが無効になることがあるためです。メッセージ・コントロールを含める必要がある場合には、セクションの外部に配置してください。その他、セクション内の個々のコントロールに対してルールを作成し、表示/非表示や必須/任意をそれぞれに設定する方法もあります。
この例のフォームに、HearingAidというセクションがあるとします。フォーム・デザイナで、HearingAid.visibleのデフォルトはfalseに設定されます。
答えがYesの場合には、HearingAid.visible=trueに設定し、セクション内部の必須フィールドはそれぞれfield.required = trueに設定する必要があります。答えがNoに変わったら、もう1つのルールでHearingAid.visible=falseに設定し、すべてのフィールドをfield.required=trueに設定する必要があります。HearingAidのセクションに多数の子コントロールがある場合、このルールはきわめて長くなり、記述する負担が大きくなります。
これを簡単にするには、セクションにrequiredプロパティを使用します。デザイナで、HearingAidの内部にあって回答が必要なコントロールをすべて必須にデフォルト設定します。HearingAidセクションを任意と非表示にデフォルト設定します。ルールはさらにシンプルにすることができます。HearingAid.required=falseに設定すると、内部コントロールはすべて再帰的にrequired=falseとなります。
if (useAid.value == 'no') { // Hide HearingAid.visible = false; HearingAid.required = false; } else { // Show HearingAid.visible = true; HearingAid.required = true; }
このルールは、ラジオ・コントロールの選択に基づいて、特定のタブを選択済タブにします。
ラジオ・ボタンはSelectTabという名前で、person、auto、homeの3つのオプションがあります。タブには、personTab、autoTab、homeTabという名前が付いています。タブは、同じ方法でトリガー・コントロールまたはその他の入力コントロールに基づいて選択することもできます。
if (SelectTab.value.length > 0) { autoTab.selected = false; homeTab.selected = false; personTab.selected = false; if (SelectTab.value == 'Auto') autoTab.selected = true; else if (SelectTab.value == 'Home') homeTab.selected = true; else personTab.selected = true; }
このフォームには、各タブの下部に「Next」というラベルの付いたトリガー・コントロールがあります。「Next」をクリックするとトリガー・ルールが実行され、次のタブが選択済タブになります。
これは、ユーザーがフォーム間を移動するときに役立ちます。タブには、T1、T2、T3、T4という名前が付けられます。トリガー・コントロールの名前はC1、C2、C3です。
// Navigate Tabs if (C1.clicked) { T2.selected = true; } else if (C2.clicked) { T3.selected = true; } else if (C3.clicked) { T4.selected = true; }
このフォームには3つのセクションがあります。最初のセクションは拡張され、2番目と3番目のセクションは縮小されています。ユーザーが1番目のセクションで提出し、「Next」トリガー・コントロールをクリックすると、そのセクションは縮小され、次のセクションが展開されます。
各トリガー・コントロールの名前はnext1およびnext2で、各セクションの名前はstep1、step2、step3です。このメンバーシップ・フォームで、ルールが機能するか試してみてください。
if(next1.clicked) { step1.expanded = false; step2.expanded = true; } if(next2.clicked) { step2.expanded = false; step3.expanded = true; }
このルールは、searchChoiceというラジオ・オプション・コントロールでのユーザーの選択に応じて、適切な入力テキスト・コントロールを表示します。
if (searchChoice.value == 'Organizations') { orgname.visible = true; firstname.visible = false; lastname.visible = false; clientId.visible = false; } else if (searchChoice.value == 'Individuals') { orgname.visible = false; firstname.visible = true; lastname.visible = true; clientId.visible = false; } else if (searchChoice.value == 'Client ID') { orgname.visible = false; firstname.visible = false; lastname.visible = false; clientId.visible = true; }
選択コントロール・オプション(ラジオ、チェック・ボックス、ドロップダウン、T/F)は、コントロールのオプション・プロパティを使用して静的にするかわりに、ルールを使用して動的に設定できます。ただし、コントロールが標準のパレット・コントロールではなくXSDスキーマ・データ・ソースに由来する場合、デザイナはオプションがそのスキーマ要素で有効な範囲から外れないように注意する必要があります。
たとえば、XSDに文字列の列挙があり、red、green、blueという有効なリスト・オプションがある場合、ルールを使用してオプションを動的にsmall、medium、largeに設定しないでください。これを行うと、使用モードでフォームが正しく機能しません。ユーザーがsmallオプションを選択すると、フォームで検証エラーが発生します。これは、smallが基礎となるXSDスキーマで許可されているオプションではないためです。
このルールは、searchという名前のトリガー・コントロールをユーザーがクリックすると実行されます。
次に、coffeeShopListという名前のドロップダウン・リスト・コントロールでオプションを動的に設定します。
if (search.clicked) { coffeeShopList.options = ['Koffee', 'Starbucks', 'Willoughbys', 'Dunkin Donuts']; }
ここで、ハードコードされたコーヒー・ショップのリストを、http.getを呼び出すルールに置き換えます。これは、JSONオブジェクトを含むX-JSONヘッダーを返す必要があります。オブジェクトが評価され、変数xに割り当てられます。この場合、JSONオブジェクトには配列タイプのオプション・フィールドが含まれます。
if (search.clicked) { eval('x=' + http.get('http://<webhost>/getCoffeeShopList')); coffeeShopList.options = x.options; }
注意:
トリガーは、繰返しアイテムでは機能しません。
このルールは、別のフォーム・フィールドで選択された値に基づいて、ドロップダウン・リストのオプションを動的に設定します。このフォームには、Products、Series、Modelという3つのフィールドがあります。シリーズのオプションは、製品の選択に基づいて動的に設定されます。
また、新しい製品が選択されたらシリーズのドロップダウンを有効にし、モデルのドロップダウンをクリアして無効にします。このフォームには、選択したシリーズに基づいてモデルを設定する他のルールも含まれています。Oracle Web Formsのギャラリで、動的フォーム・キーワードの下位にあるHP Support - 2という名前のフォームを検索します。
if (product.value == 'Laserjet Printers') { series.options = [' ', 'Laserjet5 series', 'Laserjet6 series']; series.enabled = true; model.options = []; model.enabled = false; }
このルールは、1つのドロップダウン・コントロールの選択に基づいて複数のコントロール値を設定する場合を処理します。if/elseの長い構文を使用するより適切に処理されます。
まず、SalesRepという名前のドロップダウンに<value>=<label>の形式でオプションを追加します。<value>は、各担当者に関する詳細の配列に対する索引キーとして使用されます。
Megan=Megan Smith Jim=Jim Brown Nancy=Nancy Jones Brian=Brian Jones
次に、各担当者の連絡先情報を利用してJavaScriptの配列を設定するルールを記述します。次に、contantInfo配列に対する索引としてドロップダウン値を使用し、選択した担当者の詳細を他の4つのフォーム・コントロールに設定します。
var contactInfo = { "" : { name : "", email : "", phone : "", cell : "" }, "Megan" : { name : "Megan Smith", email : MSmith@mycompany.com, phone : "(203) 694-2439 Ext. 516", cell : "(203) 337-3242" }, "Jim" : { name : "Jim Brown", email : jim@comcast.net, phone : "203-208-2999", cell : "" }, "Nancy" : { name : "Nancy Jones", email : nancy@snet.net, phone : "203-208-2991", cell : "" }, "Brian" : { name : "Brian Jones", email : BJones@mycompany.com, phone : "203-748-6502", cell : "" } }; var repId = SalesRep.value; SalesRepName.value = contactInfo[repId].name; SalesRepEmail.value = contactInfo[repId].email; SalesRepPhone.value = contactInfo[repId].phone; SalesRepCell.value = contactInfo[repId].cell;
このルールは、Usernameテキスト・フィールドにユーザーが値を入力したときに実行されます。JSONオブジェクトを返すURLを呼び出し、そのJSONオブジェクトのexistsという名前のフィールドは、ユーザーがすでに存在する場合にtrueに設定されます。ユーザーがすでに存在する場合、このルールはメッセージ・コントロールの値を設定し、そのメッセージ・コントロールをフォーム上で表示します。また、Usernameフィールドを無効として表示し、ユーザーに修正を求めるために、Usernameのvalidプロパティをfalseに設定します。
if (U.value.length > 0) { eval('x=' + http.get('http://<webhost>/uniqueUser?username=' + U.value)); if (x.exists) { M.value = 'User: ' + U.value + ' already exists'; M.visible = true; U.valid = false; } else { M.visible = false; } }
このフォームには2つのルールがあります。1番目は、資産の列に入力された値と、負債の列に入力された値を加算して純資産を計算するルールです。2番目のルールは、純資産の値をチェックし、負債が資産を超えている場合にはエラー・メッセージを表示して純資産を無効にします。その状態ではフォームが送信されないようにするためです。
if (netWorth.value < 0) { assetsExceedLiabilitiesMsg.visible = true; netWorth.valid = false; } else { assetsExceedLiabilitiesMsg.visible = false; netWorth.valid = true; }
ルールで<control>.invalidに設定されると、ユーザーが電話コントロールに無効な値を入力した場合と同様に、コントロールの背景が赤くなり、送信ボタンがグレー表示されます。Oracle Web Formsは、これを同じように扱います。これは、フォームの有効状態を動的に制御する際に適した方法です。
日付と時間の処理は、ほとんどのフォームでほぼ共通しています。次のサンプルでは、日付と時間を作成する最も一般的なビジネス・ロジックを作成する方法を示しています。
Oracle Web Formsの日付は、frevvo.currentDateTime(form)のような組込みの日付、時間および日付/時間メソッドを使用して、ユーザーのローカル・タイムゾーンに設定することができます。次のサンプルの一部では、JavaScriptのDate()オブジェクトを使用しています。ビジネス・ルールはフォーム・サーバー上で実行されるので、これらの日付も、フォーム・サーバーがインストールされている環境のタイムゾーンになります。必要な場合に異なるタイムゾーンに変換する方法も、次に示します。
日付/時間コントロールは、ビジネス・ルールの配列構文を利用して初期化する必要があります。たとえば、DtTmという日付/時間コントロールを2012年1月1日午前4:20に初期化するには、次のようにします。
DtTm.value = ['5/15/2012', '4:20']
_formTz URLパラメータを使用してフォームのUrlでタイムゾーンを指定しないかぎり、日付と時間を初期化するルールはform.loadルールでは機能しません。これは、フォーム・サーバーが日時を返すタイムゾーンを認識する必要があるためです。_formTzを指定しない場合、メソッドはnullを返し、コントロール値は空白のままになります。たとえば、東部標準時を指定するには、&_formTz=America/NewYorkとします。
このフォームは、ルールを使用して病院の退院日を初期化し、ユーザーが入院日を入力したとき2番目のルールで患者が入院していた日数を計算します。
// Calculate Hospital Stay Duration if (A.value != '' && D.value != '') { var da = A.value.split('-'); var Ams = new Date(da[2],da[0]-1,da[1]); da = D.value.split('-'); var Dms = new Date(da[2],da[0]-1,da[1]); if (Ams > Dms) { Days.value = 'Discharge date must be after Admission Date'; } else { Days.value = (Dms - Ams) / (1000*60*60*24) + ' days'; } }
Oracle Web Formsの組込みの日付および時間メソッドを使用して、日付、時間および日付/時間コントロールを、ユーザーのローカル・タイムゾーンにおける現在の日時に設定します。
if (form.load) { Tm.value = frevvo.currentTime(form); Dt.value = frevvo.currentDate(form); DtTm.value = frevvo.currentDateTime(form); }
_formTz Urlパラメータを使用してフォームのUrlでタイムゾーンを指定しないかぎり、currentTime()、currentDate()およびcurrentDateTime()はform.loadルールでは機能しません。これは、フォーム・サーバーが日時を返すタイムゾーンを認識する必要があるためです。formTzを指定しない場合、メソッドはnullを返し、コントロール値は空白のままになります。たとえば、&formTz=America/New_Yorkとすると、コントロール値は東部タイムゾーンの現在の日時に設定されます。
このルールは、Signatureという名前のコントロールを、Nameという名前のコントロールに日付/時間スタンプを加えた値に設定します。日付をユーザーのローカル・タイムゾーンに設定する場合は、Oracle Web Forms組込みの日付および時間メソッドを使用した方が適切です。次のメソッドは、日付をフォーム・サーバーのタイムゾーンに設定します。
var today=new Date() var m = today.getMonth() + 1; var d = today.getDate(); var y = today.getFullYear(); var h = today.getHours(); var min = today.getMinutes(); var todayStr = m + '-' + d + '-' + y + ' ' + h + ':' + min; Signature.value = 'Signed by ' + Name.value + ' on ' + todayStr;
このルールは、入力された日付が今日の日付より前でない場合に日付コントロールを無効にします。
var today = new Date(); var bd = DOB.value.split('-'); var bd_date = new Date(bd[0],bd[1]-1,bd[2]); if (bd_date.getTime() > today.getTime()) { MyMsg.value = 'Birth Date must be earlier than today!!!!'; DOB.valid = false; } else { MyMsg.value = 'This is a good Birth Date: ' + DOB.value; DOB.valid = true; }
このルールは、AppointmentDateという名前のコントロールに入力された値が、今日の日付から14日後を過ぎていないかどうかをチェックします。
var date1 = DateUtil.today(); var date2 = Appointment.value; date1 = date1.split("-"); date2 = date2.split("-"); var sDate = new Date(date1[0]+"/"+date1[1]+"/"+date1[2]); var eDate = new Date(date2[0]+"/"+date2[1]+"/"+date2[2]); var DaysApart = Math.round((eDate-sDate)/86400000); if (DaysApart > 14) { Appointment.status = "Date should be within 14 days from today's date."; } else if (DaysApart < 0) { Appointment.status = "Date should not be earlier to today's date."; }
このルールは、EventStartDateという名前のコントロールに入力された日付が今日から過去30日以内かどうかをチェックします。
if (EventStartDate.value != "") { var date1 = DateUtil.today(); var date2 = EventStartDate.value; date1 = date1.split("-"); date2 = date2.split("-"); var sDate = new Date(date1[0]+"/"+date1[1]+"/"+date1[2]); var eDate = new Date(date2[0]+"/"+date2[1]+"/"+date2[2]); var days = Math.round((eDate-sDate)/86400000); if (!eval(parseInt(days) > parseInt(-30))) { EventStartDate.valid = false; EventStartDate.status = "The date entered can only go back a maximum of 30 days from the current date. Please try again."; } else { EventStartDate.valid = true; }
このルールは、UTCタイムゾーンでの今日の日付を中央タイムゾーンに調整し、夏時間にも合せます。Oracleユーザーは、この追加の変換を頻繁に行う必要があります。JavaScriptのDate()とOracle Web FormsのDateUtil.today()はともに、UTCタイムゾーンで今日の日付を返すからです。
// Converts UTC to either CST or CDT if (form.load) { var today = new Date(); var DST = 1; // If today falls outside DST period, 1 extra hr offset var Central = 5; // Minimum 5 hr offset from UTC // Is it Daylight Savings Time? // var yr = today.getFullYear(); // 2nd Sunday in March can't occur after the 14th var dst_start = new Date("March 14, "+yr+" 02:00:00"); // 1st Sunday in November can't occur after the 7th var dst_end = new Date("November 07, "+yr+" 02:00:00"); var day = dst_start.getDay(); // day of week of 14th // Calculate 2nd Sunday in March of this year dst_start.setDate(14-day); day = dst_end.getDay(); // day of the week of 7th // Calculate first Sunday in November of this year dst_end.setDate(7-day); // Does today fall inside of DST period? if (today >= dst_start && today < dst_end) { DST = 0; } // Adjust Date for Central Timezone today.set Hours(today.getHours() - Central - DST); var m = today.getMonth() + 1; var d = today.getDate(); var da = today.getDay(); var y = today.getFullYear(); var h = today.getHours(); var min = today.getMinutes(); if (min < 10) { min = '0' + min;} var timezone = ['CDT', 'CST']; var dom = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; var todayStr = dom[da] + ' ' + m + '-' + d + '-' + y + ' ' + h + ':' + min + ' ' + timezone[DST]; DateTime.value = todayStr; }
このルールでは、終了時間が、開始時間より少なくとも4時間後であるが、開始時間の6時間後以前であることを確認します。また、開始時間は1:00以降である必要があります。時間は軍事単位で入力します。TSは開始時間コントロールの名前、TEは終了時間コントロールの名前です。
開始時間と終了時間にはテキスト・コントロールを使用します。
有効な軍事時間が1:00以降であることを確認するには、コントロールで([1-9]|1[0-9]|2[0-4]):([0-5][0-9])というパターンを使用します。
if (TS.value.length > 0 && TE.value.length > 0) { var sTime = TS.value.split(':'); var sHour = sTime[0]; var sMin = sTime[1]; var sMins = sHour * 60 + parseInt(sMin); var eTime = TE.value.split(':'); var eHour = eTime [0]; var eMin = eTime [1]; var eMins = eHour * 60 + parseInt(eMin); if ((eMins - sMins) < 4*60 || (eMins - sMins) > 6*60) { TE.valid = false; } else { TE.valid = true; } }
日付コントロールは、日付のみ、時間のみ、日付と時間のいずれかに設定できます。Tmという名前の時間コントロールを初期化するいくつかの例を示します。
// Both set the control name Tm to the same time Tm.value = '8:30 pm'; // uses am/pm notation Tm.vallue = ' 20:00'; // uses military time // Initialize a date/time requires an array syntax DtTm.value = ["Aug 1, 2001", "10.00"]; // Copying values Tm2.value = Tm.value; Dt2.value = Dt.value; DtTm2.value = DtTm.value;
Oracle Web Formsには、テナントのリスト、テナントにおけるユーザー、テナントにおけるロールなどフォーム・サーバーに関する情報にアクセスできるメソッドが組み込まれています。メソッドの一部は、ブール値のtrueまたはfalseを返します。それ以外はJSON文字列を返します。これらのメソッドを使用する方法のサンプルを次に示します。
if(form.load) { eval('x=' + frevvo.listTenants()); Tenants.options = x.tenants; // Init a dropdown list of all tenants on this form server } if(tenant.value.length > 0) // Check if a tenant already exists if (frevvo.isUniqueRoleId(role.value, tenant.value) == true) { ErrMsg.value = 'The role ' + role.value + ' already exists in tenant ' + tenant.value; } // Init dropdown with all tenant users eval('x=' + frevvo.listUsers(tenant.value)); Users.options = x.users; // Init dropdown with all tenant roles eval('x=' + frevvo.listRoles(tenant.value)); Roles.options = x.roles; // Init dropdown will all tenant roles except admin roles eval('x=' + frevvo.listRoles(tenant.value, false)); RolesNA.options = x.roles; }
// Verify that a role already exists in the tenant if(role.value.length > 0) { t.value = frevvo.isUniqueRoleId(role.value, tenant.value); if (frevvo.isUniqueRoleId(role.value, tenant.value) == false) { ErrMsg.value = 'The role ' + role.value + ' already exists in tenant ' + tenant.value; } }
このルールは、新しいアイテムがフォームに追加されたときに実行されます。
フォームにEmployeeという名前の繰返しセクションがあり、そこにEという名前があると仮定します。Eという名前は、セクション・コントロール上ではなくコントロール上で設定されることに注意してください。Employeeセクション・コントロールには、Name、Phoneなど多くのコントロールと、ManagerというラベルでMという名前が付いたドロップダウン・コントロールがあります。また、Employee Shift (名前はES)というラベルのラジオ・コントロールもあり、そのオプションはDayおよびEveningに設定されています。
ユーザーがフォームで「+」をクリックして新しいアイテムを追加するたびに、Oracle Web Formsはこのルールを実行します。Employee Shift ESのデフォルト値をDayに設定し、ManagerドロップダウンにはOracle Web Formsデータベース・コネクタからの値を動的に移入します。
通常は、フォーム上で最初のアイテムを表示するために、form.loadルールでドロップダウン・オプションを初期化します。
if (form.load) { var baseURL = 'http://www.myhost.com:8080/database/'; // Manager Dropdown eval('x=' + http.get(baseURL + 'Manager')); var opts = ['']; // default 1st option to blank for (var i=0; i < x.resultSet.length; i++) { if (x.resultSet[i]) { opts[i+1] = x.resultSet[i].lastname+ ", " + x.resultSet[i].firstname; } } // item index 0 is on the form by default M[0].options = opts; ES[0].value = 'Day'; // default the employee shift to Day }
ユーザーが「+」アイコンをクリックした結果として新しいアイテムが追加されたとき、データベースに戻って動的なオプションを取得するというオーバーヘッドが軽減されます。
if (E.itemAdded) { var index = E.itemIndex; // which item is this in the list // No need to go back to the database for options. // We already retrieved them in form.load rule for item index 0 M[index].options = M[0].options; ES[index].value = 'Day'; // default the employee shift to day }
表は繰返しです。表コントロールにも同じルールを記述することができます。表の繰返しの名前は、常に<TableName>Repeatです。たとえば、表にChildrenという名前を付けた場合、繰返しはChildrenRepeatという名前になります。
このルールは、新しいアイテムがフォームに追加されたときに実行されます。このフォームには、テンプレート化されたラベルを持つ繰返しセクションがあります。
新しいアイテムを追加するときには、リストが小さいグリッドに表示されるように、他のアイテムを縮小できます。Medrepeatは繰返しコントロールの名前です。Medicationは、繰返しの内部にあるセクション・コントロールの名前です。
if (MedRepeat.itemAdded) { var index = MedRepeat.itemIndex; for (var i = 0; i < Medication.value.length; i++) { if (i != index) Medication[i].expanded = false; else Medication[i].expanded = true; } }
ビジネス・ルールで参照されるとき、表はコントロールと同じです。表は、繰返しアイテムのグリッド・レイアウトです。
. この章でsについて説明しているルールの例はすべて、表にも適用されます。1つ注意しなければならないのは、表の内部ではコントロールに明示的に名前を付けることができないということです。表の内部のコントロールは、自動的に<TableName>という名前が付けられるからです。たとえば、表の名前がExpenseであれば、コントロールの名前は自動的にExpenseとなります。Expense.itemIndexとExpense.itemAddedのルールは、表に追加されたアイテムと、そのアイテムの索引をそれぞれ参照します。
ルールを使用してフィールド値を初期化することができます。これは、データベースからドロップダウン・オプションに動的に移入するとき非常に便利な機能で、多用されます。form.loadを使用するルールは、フォームが最初にロードされたときと、ワークフローがタスク・リストからロードされたときにトリガーされます。
itemAddedのみを使用するルールは、ユーザーが「+」をクリックして追加された繰返しアイテムと、初期インスタンス・ドキュメント(ドキュメントURIを参照)から追加されたアイテムに対して実行されます。フォーム・デザイナで追加したアイテムに対しては実行"されません"。フォーム・デザイナを介してデフォルトを直接追加することも、次のように2番目のルールをフォームに追加することもできます。
これらの2つのルールは、フォーム・デザイナを介してフォームにすでに存在しているコントロールの内部にあるドロップダウン・フィールドを初期化し、ユーザーがコントロールの「+」をクリックして、新しいアイテムを追加するたびにアイテムも初期化します。これらのコントロールは、別のフィールドで設定された値に基づいて初期化されます。
'''1st Rule - Default Items''' if (form.load) { // The form contains two repeat items by default. if (department.value == 'Marketing') { Managers[0].options = ['Joe', 'Mary', 'Stan', 'Cindy']; Managers[1].options = ['Joe', 'Mary', 'Stan', 'Cindy']; } if (department.value == 'Sales') { Managers[0].options = ['Lou', 'George', 'Wendy']; Managers[1].options = ['Lou', 'George', 'Wendy']; } } '''2nd Rule - Items Added''' if (Erepeat.itemAdded) { var index = Erepeat.itemIndex; // which item is this in the list ES[index].value = 'Day'; // default the employee shift to day // Use options already selected in form.load rule Managers[index].options = Manager[0].options; }
このルールは、Reviewという名前のタブを、Manager Reviewという名前のワークフロー・アクティビティにのみ表示できるようにするワークフローで使用すると便利です。
if (form.load) { if (_data.getParameter('flow.activity.name') == 'Manager Review') { Review.visible = true; } }
ルールを使用して、ユーザーがフォームの送信ボタンを押してから、フォームおよびドキュメント・アクションが実行されるまでの間に、フィールド値を初期化することができます。form.unloadを使用するルールは、フォーム・ユーザーが送信ボタンをクリックしたときにトリガーされます。また、ワークフローの場合にはユーザーが続行をクリックして次のアクティビティに進むか、完了をクリックしてフローを完了したときにトリガーされます。
代表的な例として、注文フォームの注文番号があります。注文を送信するたびに、一意の連番を注文番号として割り当てるとします。フォームの注文番号は、form.loadを使用してフォームがロードされたときに初期化することも可能です。しかし、別のユーザーが注文フォームの入力を開始したまま送信していない場合、連続する次の注文番号は、それが使用されないのであれば消費しないようにと考えます。form.unloadを使用すれば、送信ボタンがクリックされてから、フォーム・データが送信されるまでの間に番号を割り当てることができます。
ここで、OrderNumは非表示のコントロールの名前です。
if (form.unload) { eval('x=' + http.get('http://<webhost>/json/getNextOrdernum')); OrderNum.value = x.num; }
請求書、納品書などのフォームは、一意のIDの記入が必要になることがあります。連番の例もその方法の1つですが、これには制限が伴います。まず、同時にフォームを入力するのは必ず1人であることを保証する必要があります。
一意のIDが連続していなくてもいい場合の簡単なメソッドを次に示します。form.idという名前のデータは、新しいフォーム・インスタンスごとに一意であることが保証されています。次のようにこれを使用するのみです。
if (form.load) { InvoiceNum.value = _data.getParameter('form.id'); }
上のルールでは、新しく追加された繰返しコントロールを、デフォルトのオプション・リストで初期化する例を紹介しました。繰返しコントロールの値を初期化する場合にも、これと同じコンセプトが役に立ちます。
フォーム・デザイナで繰返しコントロールをフォームに追加するとき、デザイナに表示されている繰返しコントロールについてはデフォルト値を設定できます。しかし、ユーザーがフォームを使用中に「+」をクリックしてアイテムを追加する場合、フォーム・デザイナで指定されたデフォルト値はこの新しいアイテムで自動的に使用されません。これを行うために、次のような単純なルールを追加する方法があります。
このルールは、繰返しコントロールにあるフィールドの1つの値をデフォルトの0に初期化します。RepeatTrackは繰返しコントロールの名前で、albumOnlyという名前の入力コントロールが含まれます。このルールは、ユーザーが「+」をクリックして新しいRepeatTrackアイテムが追加されるたびに実行されます。
注意:
ItemAddedとitemIndexは、繰返しコントロールのプロパティです。
if (RepeatTrack.itemAdded) { var index = RepeatTrack.itemIndex; albumOnly[index].value = 0; }
フォーム・デザイナにデフォルトで存在していた繰返しアイテムを初期化するには、フォーム・デザイナに初期デフォルト値を直接入力するか、このルールを追加します。
if (form.load) { for (var i=0; i < albumOnly.value.length; i++) { albumOnly[i].value = 0; } }
このルールは、min > 1の場合に繰返しを考慮します。minが0または1の場合はもっと単純になり、fromループを削除して、if (form.load)の内部にalbumOnly[0].value = 0 inside the if (form.load)を指定するのみです。
ItemAddedは、初期ドキュメントで見つかったアイテムをOracle Web Formsが追加するときにも実行されます。初期ドキュメントから追加したアイテムは初期化せず、ユーザーがフォーム上で「+」をクリックしたときに追加したアイテムのみを初期化したい場合もあります。
このフォームには、繰返しであるMailing Labelというフィールドがあります。ラベルごとに、一意のIDを割り当てる必要があります。ただし、フォームの送信後には、割り当てられたIDはフォームのドキュメントURIを介してデータベースに保存されます。フォームのロード時には、データベースの行から自動的にアイテムが追加されます。これにはすでにIDが割り当てられています。新しいIDを連続して割り当てる必要があるのは、ユーザーがフォーム上で「+」ボタンをクリックして手動で新しい宛名ラベルを追加するときです。MLrepeatは、Mailing Labelの繰返しの名前です。MLmidはフォームのIDフィールドの名前です。
if (MLrepeat.itemAdded) { var index = MLrepeat.itemIndex; // This rule is fired both when the user clicks "+" // and when frevvo adds items found in the init doc. // Need to assign new mid only when user clicks "+" // New items added via "+" will have a zero length value. if (MLmid[index].value.length == 0) { // Assign unique ID to label so it can be referenced // in RI Mailing Labels field // Count the number of existing mailing labels on the form var maxId = 0; for (var i=0; i < MLmid.value.length; i++) { if (MLmid[i].value > maxId) { maxId = MLmid[i].value; } } var next = parseInt(maxId) + 1; MLmid[index].value = next.toFixed(0); } }