חוקי טופס
חוק טופס הוא התנהגות בצד הלקוח, שרצה בדפדפן בזמן שמשתמש צופה או עורך רשומה בדף כרטיס. כל חוק הוא זוג: conditions[] — מתי, ו‑actions[] — מה קורה ולאיזה שדה.
מה חוקי טופס אינם
Section titled “מה חוקי טופס אינם”| התכונה | חוקי טופס | טריגרים |
|---|---|---|
| איפה רצים | בדפדפן, בזמן שהמשתמש עורך | בשרת, בשמירה או בתזמון |
| היקף | טופס אחד בדף אחד | הטבלה כולה |
| אכיפה | UX בלבד — כתיבה ב‑API עוקפת אותם לגמרי | צד שרת |
| שימוש טיפוסי | הצגה מותנית, חובה מותנית, מילוי אוטומטי, נעילה אחרי סגירה | התראות, יצירת רשומות, סנכרון בין טבלאות |
Get-Form-Rules
Section titled “Get-Form-Rules”| הפרמטר | טיפוס | חובה | המשמעות |
|---|---|---|---|
pageId |
String | ✔ | הדף |
formId |
String | הטופס. ברירת מחדל — הטופס הראשון בדף | |
siteId |
String | האתר |
מחזיר { rules: [ { name, conditions[], actions[] } ] }.
זו תמיד הקריאה הראשונה — כדי לדעת מה יש ולשמור עותק. החוקים יושבים ב‑HTML של הדף, ב‑attribute data-rules של הטופס, ולכן כל כתיבה שלהם יוצרת גרסת דף — זו דרך השחזור האמיתית. בחלק מגרסאות השרת כל מה ש‑Get-Form-Rules מחזיר ניתן לשלוח חזרה כמות שהוא (round‑trip מלא), אבל זה תלוי ב‑enum האופרטורים שהשרת מגדיר באותו רגע. ראו את פירוט האופרטורים למטה ואת הערת ההיסטוריה הבאה.
מבנה החוק
Section titled “מבנה החוק”{ "name": "סיבת ביטול (חובה)", "conditions": [ { "field": "StatusId", "equesition": "equalTo", "value": "zrP1MSVBoq", "visibleVal": "בוטל", "condOr": false } ], "actions": [ { "field": "CancelReason", "action": "required", "value": "" } ]}| המפתח | חובה | המשמעות |
|---|---|---|
name |
✔ | הזהות של החוק. edit ו‑delete מאתרים לפיו |
conditions |
✔ | מערך תנאים. מותר שיהיה ריק — אבל הוא חייב להישלח |
actions |
✔ | מערך פעולות |
name הוא המזהה — לא מספר סידורי
Section titled “name הוא המזהה — לא מספר סידורי”אין ruleId. הכלי אוכף ייחודיות: add עם שם קיים מחזיר Error: Rule name already exists, ו‑edit/delete עם שם שלא קיים — Error: Rule not found. השתמשו בשמות עבריים ייחודיים ותיאוריים — הם גם מה שהמיישם הבא יקרא.
| המפתח | טיפוס | חובה | המשמעות |
|---|---|---|---|
field |
String | ✔ | השדה שמשווים |
equesition |
Enum | ✔ | האופרטור. השם משובש בשרת — כך כותבים אותו |
value |
String | Number | Boolean | ✔ | ערך ההשוואה. מותר מחרוזת ריקה, אבל המפתח חייב להישלח |
visibleVal |
String | תיאור לתצוגה בלבד | |
condOr |
Boolean | true מכניס את התנאי לקבוצת ה‑OR |
האופרטורים — שמונת הערכים הקנוניים:
equalTo · notEqualTo · greaterThan · lessThan · greaterThanOrEqualTo · lessThanOrEqualTo · containedIn · notContainedIn. לצידם קיימים בנתונים שמורים שני ערכי legacy: equealTo (איות ישן של equalTo) ו‑empty (בזמן ריצה — לשדות תאריך בלבד).
ערכי התנאי לפי סוג השדה:
| סוג השדה | value |
|---|---|
| Pointer | ה‑objectId (10 תווים). ל‑Pointer של _User מותר גם "currentUser" |
| Boolean | "checked" / "unchecked" |
| Date | "today", "year ago", YYYY-MM-DD, מספר ימים, וגם "beginning of this month", "30 days period", "end of this year", "year ahead" |
| String / Number | הערך עצמו |
AND ו‑OR
Section titled “AND ו‑OR”- תנאים בלי
condOr— כולם חייבים להתקיים. - תנאים עם
condOr: true— מרכיבים קבוצת OR אחת: מספיק שאחד מהם מתקיים. - תנאי OR בודד מתנהג כמו AND — הוא נבדק ככל תנאי אחר (תיאור הכלי אומר “no effect”; בפועל, בדפדפן, חוק עם תנאי
condOr: trueיחיד רץ רק כשהתנאי מתקיים). קבוצת OR אמיתית דורשת לפחות שניים. - שילוב: כל תנאי ה‑AND חייבים להתקיים, וגם לפחות אחד מתנאי ה‑OR.
שמונה הפעולות
Section titled “שמונה הפעולות”action |
value |
מה קורה |
|---|---|---|
hidden |
"" |
השדה נעלם מהטופס |
required |
"" |
חובה למלא לפני שמירה |
readonly |
"" |
נעול לעריכה |
fixed-value |
ערך קבוע | מציב ערך: literal · objectId ל‑Pointer · "currentUser" · מילת מפתח של תאריך · "checked"/"unchecked" לתיבת סימון |
dynamic-value |
מסלול שדה | מעתיק חי משדה אחר, כולל קפיצה אחת דרך Pointer: "AccountId.Email" |
formula-value |
— | ערך מחושב — לא ניתן לכתיבה דרך הכלים (ראו בהמשך) |
show-message |
טקסט ההודעה | מציג הודעה למשתמש (חלון קופץ; פעם אחת לכל טקסט בטעינת הדף) |
value-from-url |
(לא בשימוש) | ממלא את השדה מפרמטר ב‑query string ששמו הוא שם השדה — ?Website=… ממלא את Website; ה‑value לא נקרא |
בסכימה החיה, רק action הוא חובה בתוך אובייקט הפעולה; field ו‑value אופציונליים. פעולה שאין לה שדה — show-message — מקבלת אותו בכל זאת ברוב הדוגמאות, וזה לא מזיק. שם שדה שלא קיים בטופס מתקבל בשקט ולא עושה דבר.
dynamic-value — קפיצה אחת בלבד
Section titled “dynamic-value — קפיצה אחת בלבד”המסלול הוא דו‑חלקי: Pointer.Field — למשל AccountId.Email או BrandId.Name.
שימו לב שזה שונה מהמסלול התלת‑חלקי של טבלאות תצוגה ודוחות (AccountId.Accounts.Name). אותו רעיון, שתי דקדוקים.
יותר מקפיצה אחת אינו נתמך: הריצה קוראת רק את שני החלקים הראשונים, כך ש‑AccountId.OwnerId.name מעתיק את ה‑objectId של AccountId.OwnerId — לא את השם.
formula-value — לא ניתן לכתיבה דרך הכלים
Section titled “formula-value — לא ניתן לכתיבה דרך הכלים”fixed-value על תיבת סימון
Section titled “fixed-value על תיבת סימון”הריצה מבצעת checked = (value === "checked"): "checked" מסמן, כל ערך אחר — כולל "checkbox" שמופיע בהוראות השרת — מבטל את הסימון. ובתנאי: "checked" / "unchecked".
חוק בלי תנאים רץ תמיד
Section titled “חוק בלי תנאים רץ תמיד”"conditions": [] הוא הניב המקובל לשיקוף קבוע — “תמיד תעתיק את המייל של הלקוח לשדה הזה”.
Edit-Form-Rules — הדרך המועדפת
Section titled “Edit-Form-Rules — הדרך המועדפת”מוסיף, עורך או מוחק חוק בודד.
| הפרמטר | טיפוס | חובה | המשמעות |
|---|---|---|---|
pageId |
String | ✔ | הדף |
action |
Enum | ✔ | add · edit · delete |
rule |
Object | ✔ | החוק. name, conditions ו‑actions — כולם נדרשים |
formId |
String | הטופס. ברירת מחדל — הראשון | |
siteId |
String | האתר |
// הוספה{ "pageId": "<pageId>", "action": "add", "rule": { "name": "סיבת ביטול (חובה)", "conditions": [ { "field": "StatusId", "equesition": "equalTo", "value": "zrP1MSVBoq", "visibleVal": "בוטל" } ], "actions": [ { "field": "CancelReason", "action": "required", "value": "" } ] } }
// עריכה — התנאים והפעולות מחליפים לגמרי את של החוק הקיים באותו שם{ "pageId": "<pageId>", "action": "edit", "rule": { "name": "סיבת ביטול (חובה)", "conditions": [ … ], "actions": [ … ] } }
// מחיקה — רק השם משנה, אבל המערכים חייבים להישלח{ "pageId": "<pageId>", "action": "delete", "rule": { "name": "סיבת ביטול (חובה)", "conditions": [], "actions": [] } }Set-Form-Rules — דורס את הכול
Section titled “Set-Form-Rules — דורס את הכול”| הפרמטר | טיפוס | חובה | המשמעות |
|---|---|---|---|
pageId |
String | ✔ | הדף |
rules |
Array<Object> | ✔ | מערכת החוקים המלאה |
formId |
String | הטופס | |
siteId |
String | האתר |
מתי בכל זאת: בניית מערכת חוקים מאפס בדף חדש, או שכתוב יזום ומלא. בכל מצב אחר — Edit-Form-Rules.
הזרימה הבטוחה היחידה:
1. backup = Get-Form-Rules(pageId) שומרים את ה-JSON בצד2. newRules = backup.rules ± השינויים ממזגים, לא מחברים מהזיכרון3. Set-Form-Rules(pageId, rules: newRules)4. Get-Form-Rules(pageId) סופרים: הכמות = הבסיס ± השינוי| המצב | הכלי |
|---|---|
| הוספת חוק אחד | Edit-Form-Rules (add) |
| שינוי חוק אחד | Edit-Form-Rules (edit) |
| מחיקת חוק אחד | Edit-Form-Rules (delete) |
| מערכת חוקים מאפס בדף חדש | Set-Form-Rules |
| שכתוב מלא ומכוון | Set-Form-Rules — אחרי גיבוי |
דפוסים
Section titled “דפוסים”הזוג הסתרה + חובה
Section titled “הזוג הסתרה + חובה”הקומפוזיציה הנפוצה ביותר, ותמיד שני חוקים על אותו שדה:
[ { "name": "סיבת ביטול (הסתרה)", "conditions": [ { "field": "StatusId", "equesition": "notEqualTo", "value": "zrP1MSVBoq", "visibleVal": "בוטל" } ], "actions": [ { "field": "CancelReason", "action": "hidden", "value": "" } ] },
{ "name": "סיבת ביטול (חובה)", "conditions": [ { "field": "StatusId", "equesition": "equalTo", "value": "zrP1MSVBoq", "visibleVal": "בוטל" } ], "actions": [ { "field": "CancelReason", "action": "required", "value": "" } ] }]השדה מוסתר כל עוד הסטטוס אינו “בוטל”, וברגע שהוא הופך לבוטל — הוא מופיע וגם נדרש.
שיקוף פרטים מהלקוח
Section titled “שיקוף פרטים מהלקוח”{ "name": "שיקוף פרטי לקוח", "conditions": [], "actions": [ { "field": "Email", "action": "dynamic-value", "value": "AccountId.Email" }, { "field": "Phone", "action": "dynamic-value", "value": "AccountId.PhoneNumber" }, { "field": "Address", "action": "dynamic-value", "value": "AccountId.Address" } ] }נעילה בסטטוסים סופיים
Section titled “נעילה בסטטוסים סופיים”{ "name": "סטטוסים סופיים - קריאה בלבד", "conditions": [ { "field": "StatusId", "equesition": "equalTo", "value": "<completedId>", "visibleVal": "הושלם", "condOr": true }, { "field": "StatusId", "equesition": "equalTo", "value": "<cancelledId>", "visibleVal": "בוטל", "condOr": true } ], "actions": [ { "field": "Name", "action": "readonly", "value": "" }, { "field": "TypeId", "action": "readonly", "value": "" }, { "field": "Total", "action": "readonly", "value": "" } ] }חובה לקבוצת ערכים
Section titled “חובה לקבוצת ערכים”{ "name": "מיקום פגישה - פגישות חיצוניות", "conditions": [ { "field": "MeetingType", "equesition": "containedIn", "value": ["<externalId>", "<clientOfficeId>", "<restaurantId>"], "visibleVal": "פגישות חיצוניות" } ], "actions": [ { "field": "Location", "action": "required", "value": "" } ] }אחראי ברירת מחדל
Section titled “אחראי ברירת מחדל”{ "name": "אחראי ברירת מחדל", "conditions": [], "actions": [ { "field": "OwnerId", "action": "fixed-value", "value": "currentUser" } ] }זה גם התנאי המקדים לסינון ברמת שורה: מנגנון שמסנן רשומות לפי OwnerId שובר כשהשדה ריק.
קישור שממלא שדות מראש
Section titled “קישור שממלא שדות מראש”{ "name": "מקור הליד מה-URL", "conditions": [], "actions": [ { "field": "LeadSourceId", "action": "value-from-url", "value": "" } ] }הפרמטר נקרא בשם השדה: …/Lead?status=new&LeadSourceId=<objectId>. ה‑value אינו נקרא.
מה חוקי טופס לא יודעים לעשות
Section titled “מה חוקי טופס לא יודעים לעשות”| הבקשה | למה לא / מה במקום |
|---|---|
| לסנן את האפשרויות ברשימה נפתחת לפי שדה אחר | אין פעולה כזו. המנגנון הוא subclassDepend ב‑Edit-Page |
| לאכוף שלמות נתונים מול כתיבה ב‑API | צד לקוח בלבד. טריגרים או CLP |
| ליצור או לעדכן רשומה אחרת, לשלוח הודעה | טריגרים |
| התנהגות שונה לפי תפקיד המשתמש | אין תנאי תפקיד — התנאים קוראים רק ערכי שדות בטופס. הפתרון המעשי: allowedRoles ברמת הדף, או דף נפרד לכל קהל |
- קריאה חוזרת:
Get-Form-Rules(pageId)— החוק קיים, התנאים והפעולות תואמים, וכמות החוקים = הבסיס ± השינוי שלכם. הספירה היא מה שתופס דריסה בשוגג. - בדיקת התנהגות בדפדפן. החוקים רצים רק שם, ואין להם יומן צד שרת. פותחים את הדף, רענון קשיח (Ctrl+F5) — הגדרות החוקים נטענות עם הדף — ואז משנים את שדה התנאי ורואים את הפעולה נכנסת ויוצאת.
Get-Form-Rulesמוכיח אחסון, לא התנהגות. בלי בדיקה בדפדפן החוק אינו מאומת.
כשהחוק לא עובד — סדר הבדיקות
Section titled “כשהחוק לא עובד — סדר הבדיקות”| הבדיקה | מה מחפשים |
|---|---|
| הדף הנכון? | שולחן עבודה מול Mobile-* — לכל אחד חוקים משלו |
ה‑formId הנכון? |
בדף עם יותר מטופס אחד, ברירת המחדל היא הראשון |
| רענון קשיח? | Ctrl+F5. הגדרות החוקים נטענות עם הדף |
| ערך התנאי | objectId ולא תווית |
condOr בודד |
תנאי OR יחיד נבדק כמו AND — הוא לא “מתבטל” |
| חוק אחר על אותו שדה | החוקים רצים לפי סדר המערך: קודם מבוטלות הפעולות של החוקים שתנאיהם לא מתקיימים, ואז מופעלים החוקים שמתקיימים — החוק המאוחר גובר (שני fixed-value ללא תנאי על אותו שדה → הערך של האחרון). עדיף תנאים שסותרים זה את זה מלכתחילה |
| ציפייה שהחוק ירוץ על כתיבת API | הוא לא. לעולם |
- עריכת דפים ואלמנטים — השדות שהחוקים פועלים עליהם, ו‑
subclassDepend - כלי טריגרים ואוטומציות — כשהדרישה היא אכיפה בשרת
- תפקידים, הרשאות טבלה וחבילות — כשהדרישה היא הרשאה
- אתרים ודפים — קריאה — למצוא את
pageIdהנכון - כלי נתונים — להוציא את ה‑
objectIdשל ערכי ה‑lookup - אינדקס הכלים המלא