דלגו לתוכן

או התחילו מנקודה בטוחה: אינדקס הכלים המלא · מפת הטבלאות המרכזיות

מערכת חדשה — 14 יום חינם

טבלאות תצוגה ודפי רשימה

עודכן 30.08.2026

כל טבלה שמשתמש רואה במוצר היא אותו ווידג’ט — simbla-table — בשתי אריזות:

הצורה איפה היא חיה מי יוצר אותה מה מקבלים כברירת מחדל
דף רשימה דף עצמאי על CRMmasterapps/mybusiness/Cases, apps/mybusiness/Suppliers Create-Table-View-Page טופס חיפוש, עימוד, כפתור “חדש”
טבלה משובצת שורה בתוך דף כרטיס — המכירות בכרטיס הלקוח Add-Table-View-to-Form-Page בלי טופס חיפוש, עריכה inline, וסינון אוטומטי לרשומה הפתוחה

Edit-Table-View מגדיר את שתיהן, באותם פרמטרים בדיוק. Get-Optional-Fields מזין את שתיהן — ואת הדוחות.

הכלי הקטן שמונע את רוב התקלות בעמוד הזה.

הפרמטר טיפוס חובה המשמעות
className String המחלקה

מחזיר מתאר מוכן לכל שדה — כולל הרחבה של כל Pointer ברמה אחת (וגם createdBy / updatedBy), עם התוויות בעברית מהסכימה:

JSON
[
{ "aggrField": "Name", "field": "Name", "type": "String", "text": "שם" },
{ "aggrField": "StatusId.CaseStatuses.Name", "field": "StatusId.Name", "type": "String", "text": "סטאטוס- שם" },
{ "aggrField": "OwnerId._User.name", "field": "OwnerId.name", "type": "String", "text": "אחראי- שם" },
{ "aggrField": "AccountId.Accounts.Name", "field": "AccountId.Name", "type": "String", "text": "לקוח- שם" },
{ "aggrField": "Number", "field": "Number", "type": "AutoIncrement", "text": "מספר" }
]

מעתיקים מכאן מילה במילה את field, aggrField ו‑type. אל תחברו מסלולים ביד.

זה השדה שנופלים עליו יותר מכל אחר, כי הוא נראה כמו כפילות מיותרת של field — והוא לא:

  • field קובע מה מוצג. מסלול Pointer בנקודה אחת: AccountId.Name.
  • aggrField הוא מה שצינור הצבירה — מיון, סינון, סכימה — באמת שואל. מסלול Pointer עם שם המחלקה באמצע: AccountId.Accounts.Name.
field aggrField
Name Name
AccountId.Name AccountId.Accounts.Name
StatusId.Name StatusId.SupplierStatuses.Name — שם טבלת ה‑lookup האמיתי
OwnerId.name OwnerId._User.name
createdBy.name createdBy._User.name

יוצר דף רשימה חדש כהעתק עמוק של דף קיים.

הפרמטר טיפוס חובה המשמעות
tableName String המחלקה
pageName String הנתיב. מוסכמה: רבים, apps/mybusiness/Suppliers
copyFromPageId String הדף שממנו מעתיקים. נהוג apps/mybusiness/Cases. נאכף בוולידציה — בלעדיו הקריאה נדחית
title String הכותרת בעברית
menuName String הכותרת בתפריט הראשי — הכלי מוסיף את הפריט אוטומטית
createNewEntityTitle String כותרת כפתור היצירה, “ספק חדש”
editEntityPageName String הדף שאליו עוברים בעריכה — בדרך כלל הכרטיס
editEntityTitle String “עריכת ספק”
mainSearchTitle String “חיפוש ספקים”
searchFields Array<Object> שדות טופס החיפוש
tableColumns Array<Object> עמודות הטבלה
siteId String האתר

searchFields[]: { field ✔, equesition ✔, label, type (String|Number|Pointer), defaultValue, targetClass } tableColumns[]: { field ✔, label, type (String|Number|Boolean|Date|PrivateFile|File), aggrField }

JSON
{
"tableName": "Suppliers",
"pageName": "apps/mybusiness/Suppliers",
"copyFromPageId": "<ה-_id של דף Cases מ-Get-Site-Pages>",
"title": "ספקים",
"menuName": "ספקים",
"createNewEntityTitle": "ספק חדש",
"editEntityPageName": "Supplier",
"editEntityTitle": "עריכת ספק",
"mainSearchTitle": "חיפוש ספקים",
"searchFields": [
{ "field": "Name", "label": "שם הספק מכיל", "type": "String", "equesition": "contains" },
{ "field": "StatusId", "label": "סטטוס", "type": "Pointer", "equesition": "equalTo",
"targetClass": "SupplierStatuses" }
],
"tableColumns": [
{ "field": "Name", "label": "שם", "type": "String", "aggrField": "Name" },
{ "field": "StatusId.Name", "label": "סטטוס", "type": "String", "aggrField": "StatusId.SupplierStatuses.Name" },
{ "field": "AccountId.Name", "label": "לקוח", "type": "String", "aggrField": "AccountId.Accounts.Name" },
{ "field": "createdAt", "label": "נוצר", "type": "Date" }
]
}

הכלי מחזיר { "newPageId": "<_id>" }.

copyFromPageId — למה זו לא תבנית אלא העתק

Section titled “copyFromPageId — למה זו לא תבנית אלא העתק”

הכלי לא מייצר דף מאפס: הוא משכפל את דף המקור על כל תוכנו, ואז ממקד אותו מחדש. שלוש השלכות:

  1. המאסטר נורש מהמקור. זו הידית היחידה במוצר לבחירת מאסטר לדף חדש — ראו דפי מאסטר.
  2. גם דשבורד נוצר כך. דשבורד הוא דף רגיל על CRMmaster עם מונים וגרפים; שכפול דשבורד קיים ומיקוד מחדש של האלמנטים הוא המסלול המהיר. אז searchFields ו‑tableColumns הם placeholders מינימליים שאתם חייבים לספק. ראו אלמנטי דשבורד.
  3. כל מה שהיה בדף המקור עבר איתו — כולל דברים שאתם לא רוצים.

ניקוי שאריות אחרי יצירה מתבנית

Section titled “ניקוי שאריות אחרי יצירה מתבנית”

זה לא אופציונלי. דף שהועתק מ‑Cases נושא שאריות של Cases:

מה נורש איך מתקנים
optionalFields של Cases — סוגי פנייה בבורר העמודות Edit-Table-View עם optionalFields שלכם
classPointers בצורת Cases — מיון שבור על שדות Pointer Edit-Table-View עם classPointers מלא
כותרת SEO “Cases” בלשונית הדפדפן Set-Page-Settings(pageId, title)
קובץ ה‑JS של Cases (jsFile: …/cases.js, בהגדרות הדף) עם עקיפות עברית של Cases Set-Page-Settings(pageId, removeJSFile: true) — או jsFile משלכם. ב‑jsCode של הדף עצמו יושבת רק שורת editEntityTitle שהכלי כתב
טופס החיפוש נשאר קשור ל‑data-simbla-class="Cases" לא ניתן לתיקון מ‑Edit-Table-View (tableClassName משנה את הטבלה בלבד) — JS בדף, או שכפול דף שכבר תקין
כותרת הכפתור “פניה חדשה” ואייקון האוזניות בכותרת הדף JS בדף
כפתור “הוספת שורה” ירוק שדולף (אם מופיע) CSS: .db-form-add{display:none !important;}

שליטה מלאה בטבלה קיימת.

הפרמטר טיפוס חובה המשמעות
pageId String הדף
tableId String מזהה אלמנט הטבלה
tableClassName String המחלקה שממנה נשלפים הנתונים
columns Array העמודות המוצגות
optionalFields Array השדות שהמשתמש יכול להוסיף כעמודה
classPointers Object מפת שדה → מחלקה
filterAndSort Object סינון, חיפוש, מיון וגריד
editView Object איך נפתחת עריכת שורה
tablePermissions Object יצירה / עריכה / מחיקה בטבלה
summaryOptions Object שורת הסיכום
conditionalFormattingRules Array עיצוב מותנה
advancedOptions Object ייצוא, עריכה מרובה, ותצוגה
siteId String האתר
  • דף שנוצר ב‑Create-Table-View-Page נושא כמעט תמיד את המזהה P113, בירושה מדף Cases.
  • אחרת: Get-Page-Content(pageId, minimal: false) — הצומת עם המחלקות simblaEL simbla-table dynamic-table (דף רשימה) או simblaEL simbla-table (טבלה משובצת). ה‑id שלו הוא ה‑tableId.
  • אם ב‑minimal: true לא מצאתם את הצומת — עברו ל‑minimal: false.
  • tableId שגוי מחזיר Error: Table not found in page.
המפתח הערכים המשמעות
field מסלול התצוגה. Pointer בנקודה אחת: AccountId.Name
label כותרת העמודה
type String · Number · Boolean · Date · PrivateFile · File · HTML/XML · Pointer · Array · AutoIncrement טיפוס העמודה
aggrField מסלול הצבירה
dateFormat datetime · date · time · year · q/yy · mm/yy · month · quarter לעמודות תאריך
summary "" · sum · avg · min · max · count פונקציית הסיכום לעמודה
inlineOptions עורך inline לעמודה
subclassPointers מטא‑דאטה לעריכת Pointer inline

inlineOptions{ type: text|number|date|select|autocomplete, info, placeholder, required, readonly, parentSelect }. autocomplete לטבלאות גדולות (Accounts, _User), select ל‑lookups קטנים. parentSelect יוצר רשימות נפתחות תלויות, ואז צריך גם subclassPointers.

מפה של { "שם השדה": "שם המחלקה" }.

JSON
"classPointers": {
"createdBy": "_User", "updatedBy": "_User",
"StatusId": "SupplierStatuses", "AccountId": "Accounts", "OwnerId": "_User"
}
המפתח הערכים המשמעות
criteria מבנה תנאי B + condOr סינון ברירת מחדל, לפני שהמשתמש חיפש משהו
queryForm שם טופס החיפוש, למשל dynamic-table-formP113
queryGridSize "12" · "6" · "4" · "3" · "2" כמה רוחב לכל שדה חיפוש
queryType hard-code · form מצב סינון (מאפיין ישן)
sortBy / sortOrder · ascending / descending נכתבים כ‑data-sort-by / data-sort-orderללא השפעה על טבלה (ראו המגבלה)
sortLimit Number נכתב כ‑data-sort-limitללא השפעה על טבלה (ראו המגבלה)
waitForFirstSubmit Boolean הטבלה ריקה עד החיפוש הראשון

האופרטורים ב‑criteria של הכלי הזה הם הרשימה הרחבה ביותר במוצר — שישה‑עשר:

contains · startsWith · endsWith · equalTo · greaterThan · lessThan · greaterThanOrEqualTo · lessThanOrEqualTo · notEqualTo · containedIn · notContainedIn · exists · doesNotExist · AuthorizedOn · underMyHierarchy · notUnderMyHierarchy

שלושת האחרונים ייחודיים למוצר: “רשומות שהמשתמש מורשה עליהן”, ו“בעלים הוא אני או מי שכפוף לי”. שני האחרונים אינם עושים דבר במערכת שלא הוגדרה בה היררכיית תפקידים (הכתיבה מתקבלת). empty אינו ברשימה — הוא נדחה.

JSON
"filterAndSort": {
"queryForm": "dynamic-table-formP113", "queryGridSize": "3",
"criteria": [ { "F": "Active", "C": "equalTo", "T": "Boolean", "V": true } ]
}

ערכי תאריך ב‑V מקבלים גם מילות מפתח: "today", "year ago", "beginning of this month", "30 days period", "end of this year", "year ahead", או מספר ימים (שלילי מותר). ערך Pointer ל‑_User יכול להיות "currentUser".

openFrom ההתנהגות מתי
inline העיפרון הופך את השורה לשדות רשימות עריכה מהירה. ברירת המחדל כשאין כרטיס
modal חלון קופץ ממורכז כרטיסים עשירים
modal-left / modal-right סרגל צד נשלף חוויית הכרטיס הסטנדרטית במוצר
newwindow ניווט לדף זרימות שצריכות URL משלהן — דורש כרטיס על MasterTicket
row הטופס נפתח מתחת לשורה נדיר
hidetable הטבלה מתחלפת בטופס זרימות אשף
JSON
"editView": { "openFrom": "modal-left", "useIframe": true,
"page": "apps/mybusiness/Supplier", "popupWidthPercent": 45 }

page הוא הנתיב של דף הכרטיס (apps/mybusiness/Supplier); הסרגל נפתח עם iframe של <page>?oid=<id>&cls=<class>&Mode=iframe. אם useIframe: true ו‑page חסר או שבור — החלון נתקע על ספינר.

JSON
"tablePermissions": { "allowCreate": true, "allowEdit": true, "allowDelete": false },
"summaryOptions": { "showSum": true, "sumTitle": "סה\"כ" }

tablePermissions שולט בעיפרון, בפח ובכפתור “חדש” — ברמת התצוגה בלבד. זו לא הרשאה; משתמש עם delete ב‑CLP עדיין יכול למחוק ב‑API. ההגנה האמיתית: Set-Table-Permissions.

שורת סיכום דורשת את שניהם: summaryOptions.showSum: true וגם summary על העמודות שרוצים לסכם.

conditionalFormattingRules — עיצוב מותנה

Section titled “conditionalFormattingRules — עיצוב מותנה”
JSON
"conditionalFormattingRules": [
{ "name": "פעיל ירוק",
"conditions": [ { "field": "StatusId.Name", "fieldType": "String",
"equesition": "equalTo", "value": "פעיל" } ],
"actions": [ { "action": "cell-color", "field": "StatusId.Name", "value": "#28a745" },
{ "action": "cell-background-color", "field": "StatusId.Name", "value": "#d4edda" } ] },
{ "name": "חוב אדום מודגש",
"conditions": [ { "field": "Balance", "fieldType": "Number",
"equesition": "lessThan", "value": 0 } ],
"actions": [ { "action": "row-color", "value": "#dc3545" },
{ "action": "row-font-weight", "value": "bold" } ] }
]
  • התנאים כאן במבנה A (field / equesition / value) והם מתחברים ב‑AND. ה‑enum של הכלי: equalTo · notEqualTo · greaterThan · lessThan · greaterThanOrEqualTo · lessThanOrEqualTo · containedIn · notContainedIn · empty. בזמן ריצה empty משמעותי רק ל‑fieldType: "Date", ו‑containedIn / notContainedIn ממומשים רק ל‑Pointer.
  • דקדוק הפעולות: action הוא row-<מאפיין CSS> או cell-<מאפיין CSS> (עם field) — הקידומת מוסרת והשאר נכתב כמאפיין CSS על השורה/התא: row-color (צבע טקסט), row-background-color, row-font-weight, cell-color, cell-background-color, cell-border-color. שמות שאינם מאפיין CSS — למשל row-text-color — לא עושים דבר, ו‑hide-row אינו קיים.
  • כלל מאוחר דורס כלל מוקדם על אותו מאפיין. סדרו מהכללי לספציפי.
  • לצביעת סטטוסים בהיקף גדול עדיף שדה Color על טבלת ה‑lookup ו‑JS שמצייר תגיות — כלל לכל סטטוס אינו מתרחב יפה.
המפתח המשמעות
allowExportToExcel הפריט “ייצא לאקסל” בתפריט “…” שבכותרת עמודת העריכה. מכבד את הסינון הפעיל
exportToExcelRoles הגבלת הייצוא לתפקידים. מערך ריק = כל המשתמשים
enableMultiRowsEdit הפריט “Multi rows edit” באותו תפריט — תיבות סימון לעריכת שורות מרובות
enableMultiRowsRoles הגבלת העריכה המרובה. מערך ריק = אף אחד — חובה לציין תפקידים
showUrlAsLink הצגת URL כקישור
showLoaderAnimation אנימציית טעינה
noResultsImageUrl תמונה כשאין תוצאות
JSON
"advancedOptions": {
"allowExportToExcel": true, "exportToExcelRoles": ["Admin"],
"enableMultiRowsEdit": true, "enableMultiRowsRoles": ["Admin", "Managers"],
"showLoaderAnimation": true
}

תקרת ייצוא: לטבלה רגילה אין תקרה — הייצוא עובר על כל התוצאות במנות. ייצוא של דוח מקובץ מוגבל ל‑10,000 שורות. הייצוא רץ בדפדפן, ולכן טבלה גדולה מאוד תהיה איטית.

משבץ טבלת רשומות מקושרות בתוך דף כרטיס — הזמנות הרכש בכרטיס הספק, המכירות בכרטיס הלקוח.

הפרמטר טיפוס חובה המשמעות
pageId String דף הכרטיס
tableName String מחלקת הבן. חייבת להחזיק Pointer למחלקה של הטופס
insertAfterRow String מזהה השורה שאחריה משבצים
fields Array<Object> { fieldName ✔, label ✔, type ✔, aggrField, summary }
tableTitle String כותרת הטבלה. הכלי יוצר לה שורה משלו
createBtnTitle String כותרת כפתור ההוספה
allowCreate Boolean ברירת מחדל true
allowInlineEdit Boolean ברירת מחדל true
showSummary String כותרת שורת הסיכום. בהשמטה — אין שורת סיכום
siteId String האתר
JSON
{ "pageId": "<cardPageId>", "tableName": "SupplierOrders",
"insertAfterRow": "P319", "tableTitle": "הזמנות רכש",
"createBtnTitle": "הוסף הזמנה", "allowCreate": true, "allowInlineEdit": true,
"showSummary": "Total",
"fields": [
{ "fieldName": "Name", "label": "הזמנה", "type": "String", "aggrField": "Name" },
{ "fieldName": "StatusId.Name", "label": "סטטוס", "type": "String",
"aggrField": "StatusId.OrderStatuses.Name" },
{ "fieldName": "Amount", "label": "סכום", "type": "Number",
"aggrField": "Amount", "summary": "sum" },
{ "fieldName": "createdAt", "label": "נוצר", "type": "Date", "aggrField": "createdAt" }
] }

חמישה כללים שאסור לפספס

Section titled “חמישה כללים שאסור לפספס”
  1. ה‑Pointer הוא הסינון. כשמחלקת הבן מחזיקה שדה Pointer למחלקת הטופס, הפלטפורמה מסננת את הווידג’ט לרשומה הפתוחה אוטומטית, בלי criteria (דרך classPointers). הכלי אינו בודק זאת: מחלקה בלי Pointer מתקבלת, והווידג’ט מציג את כל הרשומות בכל כרטיס.
  2. aggrField על כל שדה. אחרת data-aggr-field="undefined" והצבירה שבורה. (שדה בלי summary מקבל data-summary="undefined" — רעש לא מזיק.)
  3. ל‑type כאן אין Pointer — רק String · Number · Boolean · Date · PrivateFile · File; Pointer נדחה בולידציה. "StatusId.Name" + String = טקסט לקריאה; "StatusId" + String = רשימה נפתחת שניתנת לעריכה, בזיהוי אוטומטי.
  4. בלי גרשיים ב‑showSummary. באג escaping ידוע: "סה\"כ" נכתב כ‑data-sum-text="סה" כ"="" — attribute שבור וכותרת “סה”. שלחו placeholder נקי, ואז Edit-Table-View עם summaryOptions.sumTitle: "סה\"כ" — שם זה נשמר נכון (&quot;).
  5. המיקום הוא הכול. ראו האזהרה הבאה.
1. Get-Optional-Fields(childClass) → field / aggrField / type / text מדויקים
2. Get-Page-Content(cardPage, minimal:false) → בוחרים insertAfterRow בטוח
3. Add-Table-View-to-Form-Page → ההצבה
4. Get-Page-Content שוב → מאמתים את האבות ולוקחים את ה-tableId
5. Edit-Table-View → classPointers מלא, סיכומים, מצב עריכה, עיצוב מותנה
  • עמודת כסף עם סיכום: עמודה {type:"Number", summary:"sum"} + summaryOptions:{showSum:true, sumTitle:"סה\"כ"}.
  • תצוגת “פעילים בלבד” שעדיין ניתנת לחיפוש: filterAndSort.criteria:[{F:"Active",C:"equalTo",T:"Boolean",V:true}].
  • עריכה מרובה למנהלים בלבד: advancedOptions:{enableMultiRowsEdit:true, enableMultiRowsRoles:["Admin","Managers"]}.
  • “המשימות שלי”: criteria:[{F:"OwnerId",C:"equalTo",T:"Pointer",V:"currentUser",P:{targetClass:"_User"}}].
  • רשימה נפתחת תלויה בעריכת inline: בעמודת הבן inlineOptions:{type:"select", parentSelect:"CaseTypes"} + subclassPointers שמונה את ה‑Pointer של האב.
  • טופס החיפוש מחוץ להיקף הכלי. אי אפשר להוסיף או לערוך שדה חיפוש דרך Edit-Table-View — רק JS בדף או שכפול דף שכבר יש בו את הטופס הנכון. אין כלי ליצירת טופס חיפוש.
  • summary: "sum" על עמודה שאינה Number מפיל את כל שורת הסיכום (400 מהשרת). ראו האזהרה ב‑summaryOptions.
  • AutoIncrement מרונדר רק אם השדה ב‑DB באמת מספר רץ. ראו כלי סכימה.
  • מזהי אלמנטים הם פר סביבה. P113 יציב בין שכפולים של אותו מקור, ולא בין לקוחות.
  • המוסכמה היא טופס חיפוש אחד לדף. שתי טבלאות בדף אחד דורשות queryForm נפרד לכל אחת — עדיף שני דפים.