Formbridgeの新バージョンにおいて、テーブル内のフラグをもとに、その行の他項目を活性or非活性にし値の変更をできないようにしたいです。
(非活性対象の項目は日付、文字列、数値フィールドなどが複数あります)
アプローチとしては2つ思い当たりましたが、どちらも失敗しました。
1,明細行ごとのフラグによるDisableまたはEditable制御(best)
2,明細行ごとのフラグによる入力値変更拒否制御(better)
1を試したところ、明細行フラグの判定はできましたがDisableが操作できませんでした。
こちらを参考にしています。
TypeError: context.getState is not a function
となっておりそもそも現在のバージョンではstateでは触れないのでは?と思います。
上記から2を試しました。
2を試したところフラグチェックと値の変更を阻止し、フィールドに対しエラー表示まで可能でした。
ですがフラグをオフにしたまま意図せず値を触ってしまった時に、
エラーを解除するまで確認画面に進めない事象が起きました。
上記の対応策として以下を試しましたがともに不発でした。
・確認ボタン押下時エラーメッセージを消去する
→エラーメッセージ発生下だと確認ボタン押下イベントが発生するまえにエラーバリデーションがかかる模様。イベントキャッチできず
・独自ボタンを設置して、値をセットし直すことでエラーメッセージを消去する
→値の再セットまでは動作しますが
エラーメッセージは消去できませんでした。
エラーが出ているフィールドを手動で操作し、エラーを解消するしかなさそうというのが現時点での見解です。
以下は、2の独自ボタンコードまで実装したスクリプトです。
すみません、実装したコードのフィールドコードに相当する部分をバッサリ切ってます。
// FormBridge テーブル内フィールド編集制御
// チェックボックス値に応じてテーブル内の他フィールドの編集を制御
(function() {
console.log('[修正チェック活性] スクリプト初期化開始');
// 設定: テーブルコード、チェックボックス、対象フィールドの定義
const config = {
'請求内容明細_A': {
checkboxFields: [{
checkbox: '修正_A_請求明細',
targetFields: [
'月日_A_請求明細',
'顧客名_A_請求明細',
'実施形態_A_請求明細',
'内容_A_請求明細',
'アシスタント_A_請求明細',
'キャンセル関連_A_請求明細',
'明細金額_税抜_A_請求明細'
]
}]
},
};
// エラー解除ボタンの追加
const addErrorCancelButton = function(context) {
try {
// エラー解除ボタンの追加
// フィールドコードが'errorCancel'の要素を検索
const errorCancelField = document.querySelector('.fb-custom--field[data-field-code="errorCancel"]');
if (errorCancelField) {
// ボタンHTML
const buttonHtml = '<button id="errorCancelButton" style="background-color: #4CAF50; color: white; padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; margin: 10px 0; font-weight: bold;">エラーを解除して確認画面へ進む</button>';
errorCancelField.innerHTML = buttonHtml;
console.log('[修正チェック活性] エラー解除ボタンを追加しました (フィールド)');
} else {
// 確認ボタンの近くに追加する代替手段
const confirmButton = document.querySelector('.fb-custom--button--confirm');
if (confirmButton && confirmButton.parentNode) {
// 新しいボタン要素を作成
const errorCancelButton = document.createElement('button');
errorCancelButton.id = 'errorCancelButton';
errorCancelButton.innerText = 'エラーを解除して確認画面へ進む';
errorCancelButton.style = 'background-color: #4CAF50; color: white; padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; margin: 10px 0; font-weight: bold;';
// 確認ボタンの前に挿入
confirmButton.parentNode.insertBefore(errorCancelButton, confirmButton);
console.log('[修正チェック活性] エラー解除ボタンを追加しました (確認ボタンの近く)');
} else {
// フォーム要素に追加する代替手段
const formElement = document.querySelector('.fb-custom--content--form');
if (formElement) {
// ボタンコンテナを作成
const buttonContainer = document.createElement('div');
buttonContainer.style = 'text-align: center; margin: 20px 0;';
// ボタン要素を作成
const errorCancelButton = document.createElement('button');
errorCancelButton.id = 'errorCancelButton';
errorCancelButton.innerText = 'エラーを解除して確認画面へ進む';
errorCancelButton.style = 'background-color: #4CAF50; color: white; padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer;';
// コンテナにボタンを追加し、フォームの最後に配置
buttonContainer.appendChild(errorCancelButton);
formElement.appendChild(buttonContainer);
console.log('[修正チェック活性] エラー解除ボタンを追加しました (フォームの最後)');
} else {
console.error('[修正チェック活性] エラー解除ボタンを追加する場所が見つかりません');
return;
}
}
}
// ボタンにクリックイベントを追加
setTimeout(function() {
const button = document.getElementById('errorCancelButton');
if (button) {
button.addEventListener('click', function(e) {
e.preventDefault();
console.log('[修正チェック活性] エラー解除ボタンがクリックされました');
clearAllErrors(context);
});
} else {
console.error('[修正チェック活性] エラー解除ボタンが見つかりません');
}
}, 500); // ボタンがDOMに反映されるまで少し待つ
} catch (error) {
console.error('[修正チェック活性] エラー解除ボタン追加エラー:', error);
}
};
// 全てのエラーをクリアする関数
const clearAllErrors = function(context) {
console.log('[修正チェック活性] 全てのエラーをクリアします');
// 全てのテーブルについて処理
for (const tableCode in config) {
const tableConfig = config[tableCode];
// テーブルのレコード数を取得
const record = context.getRecord();
const tableRows = record[tableCode] && record[tableCode].value;
if (!tableRows || !Array.isArray(tableRows)) {
console.log(`[修正チェック活性] テーブル ${tableCode} にデータがありません`);
continue;
}
// 各行について処理
for (let rowIndex = 0; rowIndex < tableRows.length; rowIndex++) {
// 各チェックボックス設定について処理
for (const checkboxConfig of tableConfig.checkboxFields) {
const { targetFields } = checkboxConfig;
// 各対象フィールドについて同じ値を再設定(エラーを上書き)
for (const fieldCode of targetFields) {
try {
// 現在の値を取得
const currentRow = tableRows[rowIndex].value;
const currentValue = currentRow[fieldCode] && currentRow[fieldCode].value;
if (currentValue !== undefined) {
// 同じ値を再設定することでエラーを上書き
context.setSubtableFieldValue(tableCode, fieldCode, rowIndex, currentValue);
// 値を再設定して更新を確定
context.setSubtableFieldValue(tableCode, fieldCode, rowIndex, currentValue);
console.log(`[修正チェック活性] フィールド値再設定: ${tableCode}.${fieldCode}[${rowIndex}] = ${currentValue}`);
}
} catch (error) {
console.error(`[修正チェック活性] フィールド値再設定エラー: ${tableCode}.${fieldCode}[${rowIndex}]`, error);
}
}
}
}
}
console.log('[修正チェック活性] エラークリア完了、確認ボタンを自動クリック');
// 確認ボタンを自動的にクリック
try {
// FormBridgeの確認ボタン要素を探す
const confirmButton = document.querySelector('.fb-custom--button--confirm');
if (confirmButton) {
confirmButton.click();
console.log('[修正チェック活性] 確認ボタンを自動クリックしました');
} else {
// 従来の方法で確認ボタンを探す代替手段
const legacyConfirmButton = document.querySelector('.gaia-ui-actionmenu-save');
if (legacyConfirmButton) {
legacyConfirmButton.click();
console.log('[修正チェック活性] 従来の確認ボタンを自動クリックしました');
} else {
console.error('[修正チェック活性] 確認ボタンが見つかりません');
}
}
} catch (error) {
console.error('[修正チェック活性] 確認ボタン自動クリックエラー:', error);
}
};
// イベントリスナーの登録
const registerEventListeners = function() {
console.log('[修正チェック活性] イベントリスナー登録開始');
// フォーム表示時のイベント
formBridge.events.on('form.show', function(context) {
console.log('[修正チェック活性] フォーム表示イベント発生');
// エラー解除ボタンを追加
setTimeout(function() {
addErrorCancelButton(context);
}, 1000); // フォームが完全に表示されるまで少し待つ
});
// 各テーブルについて処理
for (const tableCode in config) {
const tableConfig = config[tableCode];
// 各チェックボックス設定について処理
for (const checkboxConfig of tableConfig.checkboxFields) {
const { checkbox, targetFields } = checkboxConfig;
// 各対象フィールドについて、変更イベントを登録
for (const fieldCode of targetFields) {
// テーブル内フィールドの変更イベント
const eventName = `form.field.change.${tableCode}.${fieldCode}`;
// 変更イベントハンドラーの設定部分を修正
formBridge.events.on(eventName, function(context) {
console.log(`[修正チェック活性] フィールド変更イベント発生: ${tableCode}.${fieldCode}[${context.rowIndex}] = ${context.value}`);
// 現在の行のデータを取得
const record = context.getRecord();
const currentRow = record[tableCode].value[context.rowIndex].value;
// チェックボックスの値を取得
const checkboxValue = currentRow[checkbox] && currentRow[checkbox].value;
console.log(`[修正チェック活性] 修正チェック値: ${JSON.stringify(checkboxValue)}`);
// チェックボックス値が配列で"1"を含むか、または直接"1"の場合は編集を許可
const isCheckboxOn = Array.isArray(checkboxValue)
? checkboxValue.includes("1")
: checkboxValue === "1";
// チェックボックスがONでない場合、編集をキャンセル
if (!isCheckboxOn) {
console.log(`[修正チェック活性] 編集キャンセル: ${fieldCode}[${context.rowIndex}]`);
// // 変更をキャンセル
context.preventDefault();
// エラーメッセージを設定
context.setSubtableFieldValueError(
tableCode,
fieldCode,
context.rowIndex,
'修正フラグに1を入れてから編集してください'
);
// 値を元に戻す試み
return false;
} else {
// エラーメッセージをクリア
context.setSubtableFieldValueError(tableCode, fieldCode, context.rowIndex, null);
}
}, { capture: true }); // ← このオプションを追加
console.log(`[修正チェック活性] イベントリスナー登録: ${eventName}`);
}
}
}
console.log('[修正チェック活性] イベントリスナー登録完了');
};
// スクリプトの初期化
try {
console.log('[修正チェック活性] FormBridge拡張スクリプト開始');
// FormBridgeオブジェクトが存在するか確認
if (typeof formBridge === 'undefined') {
console.error('[修正チェック活性] FormBridgeオブジェクトが見つかりません');
return;
}
// イベントリスナーを登録
registerEventListeners();
console.log('[修正チェック活性] FormBridge拡張スクリプト初期化完了');
} catch (error) {
console.error('[修正チェック活性] 初期化エラー:', error);
}
})();
アプローチは問わず、達成したいことは当初の目的です。
お知恵をお借りできますと幸いです。