טבלאות תצוגה ודפי רשימה
כל טבלה שמשתמש רואה במוצר היא אותו ווידג’ט — simbla-table — בשתי אריזות:
| הצורה | איפה היא חיה | מי יוצר אותה | מה מקבלים כברירת מחדל |
|---|---|---|---|
| דף רשימה | דף עצמאי על CRMmaster — apps/mybusiness/Cases, apps/mybusiness/Suppliers |
Create-Table-View-Page |
טופס חיפוש, עימוד, כפתור “חדש” |
| טבלה משובצת | שורה בתוך דף כרטיס — המכירות בכרטיס הלקוח | Add-Table-View-to-Form-Page |
בלי טופס חיפוש, עריכה inline, וסינון אוטומטי לרשומה הפתוחה |
Edit-Table-View מגדיר את שתיהן, באותם פרמטרים בדיוק. Get-Optional-Fields מזין את שתיהן — ואת הדוחות.
Get-Optional-Fields
Section titled “Get-Optional-Fields”הכלי הקטן שמונע את רוב התקלות בעמוד הזה.
| הפרמטר | טיפוס | חובה | המשמעות |
|---|---|---|---|
className |
String | ✔ | המחלקה |
מחזיר מתאר מוכן לכל שדה — כולל הרחבה של כל Pointer ברמה אחת (וגם createdBy / updatedBy), עם התוויות בעברית מהסכימה:
[ { "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. אל תחברו מסלולים ביד.
דוקטרינת aggrField
Section titled “דוקטרינת aggrField”זה השדה שנופלים עליו יותר מכל אחר, כי הוא נראה כמו כפילות מיותרת של 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 |
Create-Table-View-Page
Section titled “Create-Table-View-Page”יוצר דף רשימה חדש כהעתק עמוק של דף קיים.
| הפרמטר | טיפוס | חובה | המשמעות |
|---|---|---|---|
tableName |
String | ✔ | המחלקה |
pageName |
String | ✔ | הנתיב. מוסכמה: רבים, apps/mybusiness/Suppliers |
copyFromPageId |
String | ✔ | הדף שממנו מעתיקים. נהוג apps/mybusiness/Cases. מאז 25.08.2026 נאכף בוולידציה — בלעדיו הקריאה נדחית (אומת 2026-08-25 17:35) |
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 }
{ "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 — למה זו לא תבנית אלא העתק”הכלי לא מייצר דף מאפס: הוא משכפל את דף המקור על כל תוכנו, ואז ממקד אותו מחדש. שלוש השלכות:
- המאסטר נורש מהמקור. זו הידית היחידה במוצר לבחירת מאסטר לדף חדש — ראו דפי מאסטר.
- גם דשבורד נוצר כך. דשבורד הוא דף רגיל על
CRMmasterעם מונים וגרפים; שכפול דשבורד קיים ומיקוד מחדש של האלמנטים הוא המסלול המהיר. אזsearchFieldsו‑tableColumnsהם placeholders מינימליים שאתם חייבים לספק. ראו אלמנטי דשבורד. - כל מה שהיה בדף המקור עבר איתו — כולל דברים שאתם לא רוצים.
ניקוי שאריות אחרי יצירה מתבנית
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;} |
Edit-Table-View
Section titled “Edit-Table-View”שליטה מלאה בטבלה קיימת.
| הפרמטר | טיפוס | חובה | המשמעות |
|---|---|---|---|
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 | האתר |
איך מוצאים tableId
Section titled “איך מוצאים tableId”- דף שנוצר ב‑
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.
columns
Section titled “columns”| המפתח | הערכים | המשמעות |
|---|---|---|
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.
classPointers
Section titled “classPointers”מפה של { "שם השדה": "שם המחלקה" }.
"classPointers": { "createdBy": "_User", "updatedBy": "_User", "StatusId": "SupplierStatuses", "AccountId": "Accounts", "OwnerId": "_User"}filterAndSort
Section titled “filterAndSort”| המפתח | הערכים | המשמעות |
|---|---|---|
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 אינו ברשימה — הוא נדחה.
"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".
editView — מצבי העריכה
Section titled “editView — מצבי העריכה”openFrom |
ההתנהגות | מתי |
|---|---|---|
inline |
העיפרון הופך את השורה לשדות | רשימות עריכה מהירה. ברירת המחדל כשאין כרטיס |
modal |
חלון קופץ ממורכז | כרטיסים עשירים |
modal-left / modal-right |
סרגל צד נשלף | חוויית הכרטיס הסטנדרטית במוצר |
newwindow |
ניווט לדף | זרימות שצריכות URL משלהן — דורש כרטיס על MasterTicket |
row |
הטופס נפתח מתחת לשורה | נדיר |
hidetable |
הטבלה מתחלפת בטופס | זרימות אשף |
"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 חסר או שבור — החלון נתקע על ספינר.
tablePermissions ו‑summaryOptions
Section titled “tablePermissions ו‑summaryOptions”"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 — עיצוב מותנה”"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 שמצייר תגיות — כלל לכל סטטוס אינו מתרחב יפה.
advancedOptions
Section titled “advancedOptions”| המפתח | המשמעות |
|---|---|
allowExportToExcel |
הפריט “ייצא לאקסל” בתפריט “…” שבכותרת עמודת העריכה. מכבד את הסינון הפעיל |
exportToExcelRoles |
הגבלת הייצוא לתפקידים. מערך ריק = כל המשתמשים |
enableMultiRowsEdit |
הפריט “Multi rows edit” באותו תפריט — תיבות סימון לעריכת שורות מרובות |
enableMultiRowsRoles |
הגבלת העריכה המרובה. מערך ריק = אף אחד — חובה לציין תפקידים |
showUrlAsLink |
הצגת URL כקישור |
showLoaderAnimation |
אנימציית טעינה |
noResultsImageUrl |
תמונה כשאין תוצאות |
"advancedOptions": { "allowExportToExcel": true, "exportToExcelRoles": ["Admin"], "enableMultiRowsEdit": true, "enableMultiRowsRoles": ["Admin", "Managers"], "showLoaderAnimation": true}תקרת ייצוא: לטבלה רגילה אין תקרה — הייצוא עובר על כל התוצאות במנות (נבדק: 307 מתוך 307 שורות). ייצוא של דוח מקובץ מוגבל ל‑10,000 שורות. הייצוא רץ בדפדפן, ולכן טבלה גדולה מאוד תהיה איטית.
Add-Table-View-to-Form-Page
Section titled “Add-Table-View-to-Form-Page”משבץ טבלת רשומות מקושרות בתוך דף כרטיס — הזמנות הרכש בכרטיס הספק, המכירות בכרטיס הלקוח.
| הפרמטר | טיפוס | חובה | המשמעות |
|---|---|---|---|
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 | האתר |
{ "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 “חמישה כללים שאסור לפספס”- ה‑Pointer הוא הסינון. כשמחלקת הבן מחזיקה שדה Pointer למחלקת הטופס, הפלטפורמה מסננת את הווידג’ט לרשומה הפתוחה אוטומטית, בלי
criteria(דרךclassPointers). הכלי אינו בודק זאת: מחלקה בלי Pointer מתקבלת, והווידג’ט מציג את כל הרשומות בכל כרטיס. aggrFieldעל כל שדה. אחרתdata-aggr-field="undefined"והצבירה שבורה. (שדה בליsummaryמקבלdata-summary="undefined"— רעש לא מזיק.)- ל‑
typeכאן איןPointer— רקString·Number·Boolean·Date·PrivateFile·File;Pointerנדחה בולידציה."StatusId.Name"+String= טקסט לקריאה;"StatusId"+String= רשימה נפתחת שניתנת לעריכה, בזיהוי אוטומטי. - בלי גרשיים ב‑
showSummary. באג escaping מאומת (mcp-d-09):"סה\"כ"נכתב כ‑data-sum-text="סה" כ"=""— attribute שבור וכותרת “סה”. שלחו placeholder נקי, ואזEdit-Table-ViewעםsummaryOptions.sumTitle: "סה\"כ"— שם זה נשמר נכון ("). - המיקום הוא הכול. ראו האזהרה הבאה.
הרצף המלא לטבלה משובצת
Section titled “הרצף המלא לטבלה משובצת”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 שוב → מאמתים את האבות ולוקחים את ה-tableId5. Edit-Table-View → classPointers מלא, סיכומים, מצב עריכה, עיצוב מותנהמתכונים
Section titled “מתכונים”- עמודת כסף עם סיכום: עמודה
{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 של האב.
מגבלות
Section titled “מגבלות”- טופס החיפוש מחוץ להיקף הכלי. אי אפשר להוסיף או לערוך שדה חיפוש דרך
Edit-Table-View— רק JS בדף או שכפול דף שכבר יש בו את הטופס הנכון. אין כלי ליצירת טופס חיפוש. summary: "sum"על עמודה שאינהNumberמפיל את כל שורת הסיכום (400 מהשרת). ראו האזהרה ב‑summaryOptions.AutoIncrementמרונדר רק אם השדה ב‑DB באמת מספר רץ. ראו כלי סכימה.- מזהי אלמנטים הם פר סביבה.
P113יציב בין שכפולים של אותו מקור, ולא בין לקוחות. - המוסכמה היא טופס חיפוש אחד לדף. שתי טבלאות בדף אחד דורשות
queryFormנפרד לכל אחת — עדיף שני דפים.
- דוחות — אותה גרמטיקה של שדות, במנוע אחר
- אלמנטי דשבורד — המונים והגרפים שיושבים לצד הטבלה
- עריכת דפים ואלמנטים · הגדרות דף, קוד וגרסאות
- כלי סכימה — טבלאות ושדות · תפקידים והרשאות
- אינדקס הכלים המלא