$p.events.before_validate
Overview¶
This explains how to specify a method to be executed before performing a validation check. Use this to check whether the value entered in the column is correct.
Limitations¶
-
If you create multiple scripts and write this function in each of them, the scripts are overwritten, so only the latest one works. For a workaround, refer to the following FAQ.
Syntax¶
JavaScript¶
$p.events.before_validate = function (args) {
//Processing content
}
or
$p.events.before_validate_{Value of the data-action attribute} = function (args) {
//Processing content
}
*Get this if you want to explicitly write the value of the data-action attribute of the button that will cause the event.
Usage Examples¶
After setting the following sample code to the Pleasanter script and setting the output destination to "Edit", the data will only be updated when you enter 100 in NumA and press the "Update" button on the edit screen (in this example, the value of the data-action attribute, Update, is explicitly stated).
JavaScript¶
$p.events.before_validate_Update = function (args) {
return ($p.getControl('NumA').val() != 100
? false //When it is false, the process stops and the update does not occur.
: true //If true, it will be updated.
);
}
Code Samples¶
Note
Modify 【 ... 】 in the code as necessary.
1. Conditional Duplicate Check by the Combination of Title, Target Month, and Creator
After the title and target date are entered, the script searches the site for an existing record with the same title whose target date falls in the same month.
Only combinations created by yourself are regarded as duplicates, and saving is stopped. Even if another user uses the same combination, it is not covered.
Criteria¶
| Creator is yourself | Title matches | Target date in the same month | Result |
|---|---|---|---|
| × | - | - | Can be saved |
| ○ | × | - | Can be saved |
| ○ | ○ | × | Can be saved |
| ○ | ○ | ○ | Error |
Practical Use Cases¶
You can use this to prevent double registration caused by operation mistakes in work where there can be several legitimate applications in the same month, such as expense claims and business trip applications.
Because the check is based not on an exact date match but on whether the target date is in the same month, it can also detect mistakes that an exact date match cannot catch, such as submitting an application with the same content (title) again on a different day in the same month.
Because it is not a business problem for other applicants to submit an application with the same title in the same month, such cases are not covered; the script is designed to catch only your own operation mistakes.
By incorporating a period-based check, "the month that the target date belongs to", this sample handles business requirements that cannot be expressed with a simple key made by combining strings.
Note
Do not use this together with the standard "Duplication prohibited" function. (That function always blocks duplicates per column across all records, so the "period-based check" and "limited to yourself" of this sample are not applied.)
Preparations¶
- Prepare a title column (the standard Title) and a date column (Target Date, column code: DateA) in the table.
- Register the script.
- On the "Manage table > Scripts" tab, select "New".
- Title: Any name (example: Duplicate check of title and target month)
- Script: Paste the sample code below
- Output to: Select both "New" and "Edit"
// ===== Settings =====
const SITE_ID = $p.siteId();
const TITLE_COLUMN = 'Title';
const DATE_COLUMN = 'DateA';
const OWNER_COLUMN = 'Owner';
const buildDuplicateMessage = (matchedId) => `The content is the same as ID:${matchedId}.`;
// ===== State =====
let hasDuplicate = false; // Whether the current input is a duplicate
let duplicateMessage = ''; // Error message to display
let eventsBound = false; // Whether the change events have been registered (prevents duplicate registration)
// Get the first and last days of the month from the target date string ("yyyy/MM/dd", etc.)
function getMonthRange(dateStr) {
if (!dateStr) {
return null;
}
const [year, month] = dateStr.split('T')[0].split(/[/-]/).map(Number);
const firstDay = new Date(year, month - 1, 1);
const lastDay = new Date(year, month, 0);
return { firstDay, lastDay };
}
// Convert a Date to a string in "yyyy/MM/dd" format (used to specify the search condition)
function formatDate(date) {
const parts = [date.getFullYear(), date.getMonth() + 1, date.getDate()];
return parts.map((n, i) => i === 0 ? n : String(n).padStart(2, '0')).join('/');
}
// Determine whether a record is a duplicate of the content being entered
// Conditions: the creator is yourself, the title matches, and the target date is in the same month
function isSameRecord(record, title, monthRange, currentUserId) {
if (record[OWNER_COLUMN] !== currentUserId || record[TITLE_COLUMN] !== title) {
return false;
}
const recordDateStr = record.DateHash ? record.DateHash[DATE_COLUMN] : null;
if (!recordDateStr) {
return false;
}
const [ry, rm, rd] = recordDateStr.split('T')[0].split(/[/-]/).map(Number);
const recordDate = new Date(ry, rm - 1, rd);
return recordDate >= monthRange.firstDay && recordDate <= monthRange.lastDay;
}
// Search the site for duplicate records based on the title and target date
// Keep the result in hasDuplicate / duplicateMessage, and use it for the check at save time
function checkDuplicate(ownRecordId) {
const title = $p.getValue(TITLE_COLUMN);
const targetDateStr = $p.getValue(DATE_COLUMN);
const currentUserId = $p.userId();
hasDuplicate = false;
duplicateMessage = '';
$p.clearMessage();
const monthRange = getMonthRange(targetDateStr);
if (!title || !monthRange) {
return;
}
$p.apiGet({
id: SITE_ID,
data: {
View: {
ColumnFilterHash: {
Title: title,
[DATE_COLUMN]: `${formatDate(monthRange.firstDay)},${formatDate(monthRange.lastDay)}`
}
}
},
done: function (data) {
const allRecords = (data && data.Response && data.Response.Data) || [];
const exactMatches = allRecords.filter(function (record) {
if (ownRecordId !== null && record.ResultId === ownRecordId) {
return false;
}
return isSameRecord(record, title, monthRange, currentUserId);
});
if (exactMatches.length > 0) {
hasDuplicate = true;
duplicateMessage = buildDuplicateMessage(exactMatches[0].ResultId);
$p.setMessage('#Message', JSON.stringify({
Css: 'alert-error',
Text: duplicateMessage
}));
}
},
fail: function () {
console.log('The search for the duplicate check failed.');
}
});
}
// When the screen is displayed: check once with the current content, and then check again each time the title or target date is changed
$p.events.on_editor_load = function () {
const action = $p.action();
if (action !== 'new' && action !== 'edit') {
return;
}
const ownRecordId = action === 'edit' ? $p.id() : null;
checkDuplicate(ownRecordId);
if (eventsBound) {
return;
}
eventsBound = true;
$p.on('change', TITLE_COLUMN, function () {
checkDuplicate(ownRecordId);
});
$p.on('change', DATE_COLUMN, function () {
checkDuplicate(ownRecordId);
});
};
// Just before saving: stop saving if there is a duplicate
$p.events.before_validate_Create =
$p.events.before_validate_Update = function (args) {
if (hasDuplicate) {
$p.clearMessage();
$p.setMessage('#Message', JSON.stringify({
Css: 'alert-error',
Text: duplicateMessage
}));
return false;
}
return true;
};
Test Data¶
ID:2001 Title: Meeting expenses Target date: 2026/07/15 Creator: User A
ID:2002 Title: Transportation expenses Target date: 2026/08/03 Creator: User A
ID:2003 Title: Business trip expenses Target date: 2026/08/05 Creator: User B
ID:2004 Title: Entertainment expenses Target date: 2026/08/10 Creator: User A
Execution Result 1 (User A enters the title "Meeting expenses" and the target date "2026/08/28", and saves)¶
No message is displayed.
(The title matches ID:2001 registered by User A, but ID:2001 is in July, so the target month is different. The record can be saved.)
Execution Result 2 (User A enters the title "Development expenses" and the target date "2026/08/10", and saves)¶
No message is displayed.
(The target date is close to ID:2004 registered by User A, but the title "Entertainment expenses" does not match, so it is not covered. The record can be saved.)
Execution Result 3 (User A enters the title "Business trip expenses" and the target date "2026/08/05", and saves)¶
No message is displayed.
(ID:2003 matches in both title and month, but its creator is User B, so it is not covered. The record can be saved.)
Execution Result 4 (User A enters the title "Transportation expenses" and the target date "2026/08/20", and saves)¶
(The creator and title match, and the target date is also in August, so an error occurs and saving is stopped.)
Related Information¶
FAQ: I want to be able to set multiple $p.events.on_editor_load