kintoneで相対日付のバリデーションを行う
先日kintoneで宣言的にフィールド値の検証を行うという記事を投稿しました。Tynderというライブラリを使い、型宣言を書くことで、(手続き的ではなく)宣言的に入力値の検証を行いました。
今回はその応用編として、日付や日付時刻型のフィールドを相対日付(例えば、今月、来月、今年、今年度)で検証します。
さらに、フィールドのエラーに合ったカスタムエラーメッセージを表示するようにします。
コード
- tynder.min.js
-
lib.js (前回記事)
- app.js (下述)
// アプリのレコード型を定義します
// interfaceの各フィールドは、kintoneアプリのフィールドコードと一致させてください
const definition = `
/** サブテーブル */
interface Table {
itemName: string;
itemValue: number;
}
/** アプリ */
interface App {
/** 名称 */
@minLength(2) @maxLength(16)
@match(/^[A-Z][0-9]{3}-.+/)
name: string;
/** 数量 (非必須) */
amount?: number;
/** 期日 */
@stereotype('lcdate') // ローカルタイムゾーン日付
@range('=today first-date-of-mo', '=today last-date-of-mo')
@msg({
valueRangeUnmatched: '当月の日付を入力してください',
})
dueDate: string;
/** 最終接点日時 */
@stereotype('lcdatetime') // ローカルタイムゾーン日付時刻
@minValue('=today first-date-of-mo') @lessThan('=today last-date-of-mo +1day')
@msg({
valueRangeUnmatched: '当月の日付時刻を入力してください',
})
contactDt: string;
/** サブテーブル */
table: Table[];
}
`;
// イベントハンドラ
kintone.events.on([
'app.record.create.submit',
'mobile.app.record.create.submit',
'app.record.edit.submit',
'mobile.app.record.edit.submit',
'app.record.index.edit.submit',
], function(event) {
event.record = removeBlankTableRow(event.record, 'table');
// スキーマ検証を行います
const schema = tynder.compile(definition);
const ctx = {
checkAll: true,
schema,
stereotypes: new Map(tynder.stereotypes),
// 共通のカスタムエラーメッセージ
errorMessages: {
required: '必須です',
valueLengthUnmatched: '値は%{minLength}から%{maxLength}の長さで入れてください',
valueRangeUnmatched: '値は%{minValue}から%{maxValue}の間で入れてください',
typeUnmatched: '値の形式が間違っています',
},
};
const unknownInput = mapRecord(event.record);
const validated = tynder.validate(unknownInput, tynder.getType(schema, 'App'), ctx);
if (! validated) {
const errText = JSON.stringify(ctx.errors, null, 2);
console.error(errText);
// エラーを表示します
displayValidationErrorMessages(event, ctx);
}
return event;
});
日付時刻数式
- 今月(日付)
@range('=today first-date-of-mo', '=today last-date-of-mo')
- 今月(日付時刻)
@minValue('=today first-date-of-mo') @lessThan('=today last-date-of-mo +1day')
- 来月(日付)
@range('=today first-date-of-mo +1mo', '=today @1day +1mo last-date-of-mo')
- 来月(日付時刻)
@minValue('=today first-date-of-mo +1mo') @lessThan('=today @1day +1mo last-date-of-mo +1day')
- 今年(日付)
@range('=today first-date-of-yr', '=today last-date-of-yr')
- 今年(日付時刻)
@minValue('=today first-date-of-yr') @lessThan('=today last-date-of-yr +1day')
- 来年(日付)
@range('=today first-date-of-yr +1yr', '=today @1day +1yr last-date-of-yr')
- 来年(日付時刻)
@minValue('=today first-date-of-yr +1yr') @lessThan('=today @1day +1yr last-date-of-yr +1day')
- 今年度(date)
-
@range('=today first-date-of-fy(4)', '=today first-date-of-fy(4) +1yr -1day')
- 4月始まり
- 今年度(datetime)
-
@minValue('=today first-date-of-fy(4)') @lessThan('=today first-date-of-fy(4) +1yr')
- 4月始まり
- 来年度(日付)
-
@range('=today first-date-of-fy(4) +1yr', '=today first-date-of-fy(4) +2yr -1day')
- 4月始まり
- 来年度(日付時刻)
-
@minValue('=today first-date-of-fy(4) +1yr') @lessThan('=today first-date-of-fy(4) +2yr')
- 4月始まり
// アプリのレコード型を定義します
// interfaceの各フィールドは、kintoneアプリのフィールドコードと一致させてください
const definition = `
/** サブテーブル */
interface Table {
itemName: string;
itemValue: number;
}
/** アプリ */
interface App {
/** 名称 */
@minLength(2) @maxLength(16)
@match(/^[A-Z][0-9]{3}-.+/)
name: string;
/** 数量 (非必須) */
amount?: number;
/** 期日 */
@stereotype('lcdate') // ローカルタイムゾーン日付
@range('=today first-date-of-mo', '=today last-date-of-mo')
@msg({
valueRangeUnmatched: '当月の日付を入力してください',
})
dueDate: string;
/** 最終接点日時 */
@stereotype('lcdatetime') // ローカルタイムゾーン日付時刻
@minValue('=today first-date-of-mo') @lessThan('=today last-date-of-mo +1day')
@msg({
valueRangeUnmatched: '当月の日付時刻を入力してください',
})
contactDt: string;
/** サブテーブル */
table: Table[];
}
`;
// イベントハンドラ
kintone.events.on([
'app.record.create.submit',
'mobile.app.record.create.submit',
'app.record.edit.submit',
'mobile.app.record.edit.submit',
'app.record.index.edit.submit',
], function(event) {
event.record = removeBlankTableRow(event.record, 'table');
// スキーマ検証を行います
const schema = tynder.compile(definition);
const ctx = {
checkAll: true,
schema,
stereotypes: new Map(tynder.stereotypes),
// 共通のカスタムエラーメッセージ
errorMessages: {
required: '必須です',
valueLengthUnmatched: '値は%{minLength}から%{maxLength}の長さで入れてください',
valueRangeUnmatched: '値は%{minValue}から%{maxValue}の間で入れてください',
typeUnmatched: '値の形式が間違っています',
},
};
const unknownInput = mapRecord(event.record);
const validated = tynder.validate(unknownInput, tynder.getType(schema, 'App'), ctx);
if (! validated) {
const errText = JSON.stringify(ctx.errors, null, 2);
console.error(errText);
// エラーを表示します
displayValidationErrorMessages(event, ctx);
}
return event;
});
- 今月(日付)
@range('=today first-date-of-mo', '=today last-date-of-mo')
- 今月(日付時刻)
@minValue('=today first-date-of-mo') @lessThan('=today last-date-of-mo +1day')
- 来月(日付)
@range('=today first-date-of-mo +1mo', '=today @1day +1mo last-date-of-mo')
- 来月(日付時刻)
@minValue('=today first-date-of-mo +1mo') @lessThan('=today @1day +1mo last-date-of-mo +1day')
- 今年(日付)
@range('=today first-date-of-yr', '=today last-date-of-yr')
- 今年(日付時刻)
@minValue('=today first-date-of-yr') @lessThan('=today last-date-of-yr +1day')
- 来年(日付)
@range('=today first-date-of-yr +1yr', '=today @1day +1yr last-date-of-yr')
- 来年(日付時刻)
@minValue('=today first-date-of-yr +1yr') @lessThan('=today @1day +1yr last-date-of-yr +1day')
- 今年度(date)
-
@range('=today first-date-of-fy(4)', '=today first-date-of-fy(4) +1yr -1day')
- 4月始まり
-
- 今年度(datetime)
-
@minValue('=today first-date-of-fy(4)') @lessThan('=today first-date-of-fy(4) +1yr')
- 4月始まり
-
- 来年度(日付)
-
@range('=today first-date-of-fy(4) +1yr', '=today first-date-of-fy(4) +2yr -1day')
- 4月始まり
-
- 来年度(日付時刻)
-
@minValue('=today first-date-of-fy(4) +1yr') @lessThan('=today first-date-of-fy(4) +2yr')
- 4月始まり
-
詳しくは https://github.com/shellyln/tynder#date--datetime-stereotypes を参照してください。
型宣言のテストについて
記述した型宣言が文法的に正しいかどうかは以下のサイトで確認できます。
https://shellyln.github.io/tynder/playground2.html
Author And Source
この問題について(kintoneで相対日付のバリデーションを行う), 我々は、より多くの情報をここで見つけました https://qiita.com/shellyln/items/2beae1c7f41ba019b1d2著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .