@memberjunction/ng-join-grid 1.7.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,25 +1,40 @@
1
- import { AfterViewInit, ChangeDetectorRef } from '@angular/core';
2
- import { BaseEntity, EntityInfo } from '@memberjunction/core';
1
+ import { AfterViewInit, ChangeDetectorRef, ElementRef } from '@angular/core';
2
+ import { BaseEntity, EntityFieldInfo, EntityInfo } from '@memberjunction/core';
3
3
  import * as i0 from "@angular/core";
4
4
  export declare class JoinGridCell {
5
5
  index: number;
6
6
  RowForeignKeyValue: any;
7
- ColumnForeignKeyValue: any;
8
- data: BaseEntity | undefined;
7
+ ColumnForeignKeyValue?: any;
8
+ /**
9
+ * Used when the ColumnsMode is set to Entity. This is the BaseEntity object that represents the data in the JoinEntity that links the Row and Column entities together.
10
+ */
11
+ data?: BaseEntity | undefined;
12
+ /**
13
+ * Used when the ColumnsMode is set to Fields. This is an array of values from the JoinEntity that are displayed as columns in the grid.
14
+ */
15
+ value?: any;
9
16
  }
10
17
  export declare class JoinGridRow {
11
18
  FirstColValue: any;
12
19
  JoinExists: boolean;
13
20
  RowForeignKeyValue: any;
14
21
  ColumnData: JoinGridCell[];
22
+ GetColumnValue(colIndex: number): any;
23
+ constructor(data: any);
15
24
  }
16
25
  export declare class JoinGridComponent implements AfterViewInit {
17
26
  private cdr;
27
+ private elementRef;
18
28
  /**
19
29
  * Required: the name of the entity that will be used for displaying data for rows. This means that each row in the RowsEntity will be shown as a row in the grid
20
30
  * where the RowsEntityDisplayField will be used in the first column of the grid.
21
31
  */
22
32
  RowsEntityName: string;
33
+ /**
34
+ * Optional: if provided, this value will be shown in the top-left corner of the grid instead of the RowsEntityName
35
+ */
36
+ RowsEntityDisplayName?: string;
37
+ get RowsEntityDisplayNameOrName(): string;
23
38
  /**
24
39
  * Required: the field name in the RowsEntityName that will be shown in the first column in the grid
25
40
  */
@@ -99,6 +114,12 @@ export declare class JoinGridComponent implements AfterViewInit {
99
114
  */
100
115
  JoinEntityDisplayColumns?: string[];
101
116
  /**
117
+ * When specified, this filter is used to further constrain the data in the JoinEntity. This is optional but is generally
118
+ * most useful when ColumnsMode is set to Fields and you want to filter the data in the JoinEntity based on some criteria.
119
+ */
120
+ JoinEntityExtraFilter?: string;
121
+ /**
122
+ * ONLY USED WHEN ColumnsMode=Entity
102
123
  * When this property is set to JoinRecordExists the grid will operate as follows:
103
124
  * * When a user checks the checkbox in the grid, a record will be created in the JoinEntity with the Row and Column foreign keys.
104
125
  * * When a user unchecks the checkbox in the grid, the record in the JoinEntity will be deleted.
@@ -118,14 +139,27 @@ export declare class JoinGridComponent implements AfterViewInit {
118
139
  NewRecordDefaultValues?: {
119
140
  [key: string]: any;
120
141
  };
121
- ngAfterViewInit(): void;
122
- constructor(cdr: ChangeDetectorRef);
142
+ /**
143
+ * When set to true, the Save button is shown
144
+ */
145
+ ShowSaveButton: boolean;
146
+ /**
147
+ * When set to true, the Cancel button is shown
148
+ */
149
+ ShowCancelButton: boolean;
150
+ /**
151
+ * Change the value of this property to true or false when you want to enter or exit edit mode. Only use this when the grid
152
+ * is embedded in another form and you are not showing the built-in save/cancel buttons
153
+ */
154
+ EditMode: 'None' | 'Save' | 'Queue';
155
+ constructor(cdr: ChangeDetectorRef, elementRef: ElementRef);
123
156
  _GridData: JoinGridRow[];
124
157
  _IsLoading: boolean;
125
158
  protected _rowsEntityInfo: EntityInfo | null;
126
159
  protected _columnsEntityInfo: EntityInfo | null;
127
160
  protected _columnsEntityData: BaseEntity[] | undefined;
128
161
  protected _rowsEntityData: BaseEntity[] | undefined;
162
+ protected _joinEntityData: BaseEntity[] | undefined;
129
163
  /**
130
164
  * Saves all of the changes made in the grid. This includes adding new records, updating existing records, and deleting records.
131
165
  */
@@ -143,11 +177,37 @@ export declare class JoinGridComponent implements AfterViewInit {
143
177
  Refresh(): Promise<void>;
144
178
  protected PopulateRowsAndColsData(): Promise<void>;
145
179
  protected RunColumnsOrRowsView(dataSource: 'FullEntity' | 'ViewName', entityName: string, viewName?: string, extraFilter?: string, orderBy?: string): Promise<BaseEntity[]>;
146
- protected PopulateGridData(joinEntityData: BaseEntity[]): Promise<void>;
180
+ protected PopulateGridData(): Promise<void>;
147
181
  protected _pendingDeletes: BaseEntity[];
148
182
  protected _pendingInserts: BaseEntity[];
149
183
  _FlipRecord(event: MouseEvent, row: JoinGridRow, cell: JoinGridCell, stopPropagation?: boolean): Promise<void>;
150
184
  _IsColumnChecked(cell: JoinGridCell): boolean;
185
+ UpdateCellValueDirect(row: JoinGridRow, colIndex: number, newValue: string): Promise<void>;
186
+ UpdateCellValue(row: JoinGridRow, colIndex: number, event: Event): Promise<void>;
187
+ /**
188
+ * Only used when ColumnsMode = Fields
189
+ * @param row
190
+ */
191
+ RemoveJoinEntityRecord(row: JoinGridRow): Promise<void>;
192
+ /**
193
+ * Only used when ColumnsMode = Fields
194
+ */
195
+ AddJoinEntityRecord(row: JoinGridRow): Promise<void>;
196
+ protected EditingComplete(): Promise<void>;
197
+ protected RevertPendingChanges(): Promise<void>;
198
+ ngAfterViewInit(): void;
199
+ /**
200
+ * Returns the EntityFieldInfo that matches the specific column name within the JoinEntity
201
+ * @param colName
202
+ */
203
+ GetJoinEntityField(colName: string): EntityFieldInfo;
204
+ GetJoinEntityFieldValues(colName: string): string[];
205
+ get EntityFieldTSType(): {
206
+ readonly String: "string";
207
+ readonly Number: "number";
208
+ readonly Date: "Date";
209
+ readonly Boolean: "boolean";
210
+ };
151
211
  static ɵfac: i0.ɵɵFactoryDeclaration<JoinGridComponent, never>;
152
- static ɵcmp: i0.ɵɵComponentDeclaration<JoinGridComponent, "mj-join-grid", never, { "RowsEntityName": { "alias": "RowsEntityName"; "required": false; }; "RowsEntityDisplayField": { "alias": "RowsEntityDisplayField"; "required": false; }; "RowsEntityDataSource": { "alias": "RowsEntityDataSource"; "required": false; }; "RowsExtraFilter": { "alias": "RowsExtraFilter"; "required": false; }; "RowsOrderBy": { "alias": "RowsOrderBy"; "required": false; }; "RowsEntityViewName": { "alias": "RowsEntityViewName"; "required": false; }; "RowsEntityArray": { "alias": "RowsEntityArray"; "required": false; }; "ColumnsMode": { "alias": "ColumnsMode"; "required": false; }; "ColumnsEntityName": { "alias": "ColumnsEntityName"; "required": false; }; "ColumnsEntityDisplayField": { "alias": "ColumnsEntityDisplayField"; "required": false; }; "ColumnsEntityDataSource": { "alias": "ColumnsEntityDataSource"; "required": false; }; "ColumnsExtraFilter": { "alias": "ColumnsExtraFilter"; "required": false; }; "ColumnsOrderBy": { "alias": "ColumnsOrderBy"; "required": false; }; "ColumnsEntityViewName": { "alias": "ColumnsEntityViewName"; "required": false; }; "ColumnsEntityArray": { "alias": "ColumnsEntityArray"; "required": false; }; "JoinEntityName": { "alias": "JoinEntityName"; "required": false; }; "JoinEntityRowForeignKey": { "alias": "JoinEntityRowForeignKey"; "required": false; }; "JoinEntityColumnForeignKey": { "alias": "JoinEntityColumnForeignKey"; "required": false; }; "JoinEntityDisplayColumns": { "alias": "JoinEntityDisplayColumns"; "required": false; }; "CheckBoxValueMode": { "alias": "CheckBoxValueMode"; "required": false; }; "CheckBoxValueField": { "alias": "CheckBoxValueField"; "required": false; }; "NewRecordDefaultValues": { "alias": "NewRecordDefaultValues"; "required": false; }; }, {}, never, never, false, never>;
212
+ static ɵcmp: i0.ɵɵComponentDeclaration<JoinGridComponent, "mj-join-grid", never, { "RowsEntityName": { "alias": "RowsEntityName"; "required": false; }; "RowsEntityDisplayName": { "alias": "RowsEntityDisplayName"; "required": false; }; "RowsEntityDisplayField": { "alias": "RowsEntityDisplayField"; "required": false; }; "RowsEntityDataSource": { "alias": "RowsEntityDataSource"; "required": false; }; "RowsExtraFilter": { "alias": "RowsExtraFilter"; "required": false; }; "RowsOrderBy": { "alias": "RowsOrderBy"; "required": false; }; "RowsEntityViewName": { "alias": "RowsEntityViewName"; "required": false; }; "RowsEntityArray": { "alias": "RowsEntityArray"; "required": false; }; "ColumnsMode": { "alias": "ColumnsMode"; "required": false; }; "ColumnsEntityName": { "alias": "ColumnsEntityName"; "required": false; }; "ColumnsEntityDisplayField": { "alias": "ColumnsEntityDisplayField"; "required": false; }; "ColumnsEntityDataSource": { "alias": "ColumnsEntityDataSource"; "required": false; }; "ColumnsExtraFilter": { "alias": "ColumnsExtraFilter"; "required": false; }; "ColumnsOrderBy": { "alias": "ColumnsOrderBy"; "required": false; }; "ColumnsEntityViewName": { "alias": "ColumnsEntityViewName"; "required": false; }; "ColumnsEntityArray": { "alias": "ColumnsEntityArray"; "required": false; }; "JoinEntityName": { "alias": "JoinEntityName"; "required": false; }; "JoinEntityRowForeignKey": { "alias": "JoinEntityRowForeignKey"; "required": false; }; "JoinEntityColumnForeignKey": { "alias": "JoinEntityColumnForeignKey"; "required": false; }; "JoinEntityDisplayColumns": { "alias": "JoinEntityDisplayColumns"; "required": false; }; "JoinEntityExtraFilter": { "alias": "JoinEntityExtraFilter"; "required": false; }; "CheckBoxValueMode": { "alias": "CheckBoxValueMode"; "required": false; }; "CheckBoxValueField": { "alias": "CheckBoxValueField"; "required": false; }; "NewRecordDefaultValues": { "alias": "NewRecordDefaultValues"; "required": false; }; "ShowSaveButton": { "alias": "ShowSaveButton"; "required": false; }; "ShowCancelButton": { "alias": "ShowCancelButton"; "required": false; }; "EditMode": { "alias": "EditMode"; "required": false; }; }, {}, never, never, false, never>;
153
213
  }
@@ -8,107 +8,235 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { Component, Input } from '@angular/core';
11
- import { Metadata, RunView } from '@memberjunction/core';
11
+ import { EntityFieldTSType, LogError, Metadata, RunView } from '@memberjunction/core';
12
+ import { MJEventType, MJGlobal } from '@memberjunction/global';
13
+ import { SharedService } from '@memberjunction/ng-shared';
14
+ import { BaseFormComponentEventCodes } from '@memberjunction/ng-base-types';
12
15
  import * as i0 from "@angular/core";
13
16
  import * as i1 from "@angular/common";
14
- import * as i2 from "@progress/kendo-angular-buttons";
15
- import * as i3 from "@progress/kendo-angular-indicators";
16
- import * as i4 from "@memberjunction/ng-container-directives";
17
+ import * as i2 from "@progress/kendo-angular-inputs";
18
+ import * as i3 from "@progress/kendo-angular-buttons";
19
+ import * as i4 from "@progress/kendo-angular-dropdowns";
20
+ import * as i5 from "@progress/kendo-angular-indicators";
21
+ import * as i6 from "@memberjunction/ng-container-directives";
17
22
  function JoinGridComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
18
23
  i0.ɵɵelementStart(0, "div");
19
24
  i0.ɵɵelement(1, "kendo-loader");
20
25
  i0.ɵɵelementEnd();
21
26
  } }
22
- function JoinGridComponent_Conditional_6_Conditional_5_For_1_Template(rf, ctx) { if (rf & 1) {
23
- i0.ɵɵelementStart(0, "th");
27
+ function JoinGridComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
28
+ const _r1 = i0.ɵɵgetCurrentView();
29
+ i0.ɵɵelementStart(0, "button", 3);
30
+ i0.ɵɵlistener("click", function JoinGridComponent_Conditional_2_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Save()); });
31
+ i0.ɵɵtext(1, "Save");
32
+ i0.ɵɵelementEnd();
33
+ } if (rf & 2) {
34
+ const ctx_r1 = i0.ɵɵnextContext();
35
+ i0.ɵɵproperty("disabled", ctx_r1.NumDirtyRecords === 0);
36
+ } }
37
+ function JoinGridComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
38
+ const _r3 = i0.ɵɵgetCurrentView();
39
+ i0.ɵɵelementStart(0, "button", 3);
40
+ i0.ɵɵlistener("click", function JoinGridComponent_Conditional_3_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.CancelEdit()); });
41
+ i0.ɵɵtext(1, "Cancel");
42
+ i0.ɵɵelementEnd();
43
+ } if (rf & 2) {
44
+ const ctx_r1 = i0.ɵɵnextContext();
45
+ i0.ɵɵproperty("disabled", ctx_r1.NumDirtyRecords === 0);
46
+ } }
47
+ function JoinGridComponent_Conditional_4_Conditional_5_For_1_Template(rf, ctx) { if (rf & 1) {
48
+ i0.ɵɵelementStart(0, "th", 5);
24
49
  i0.ɵɵtext(1);
25
50
  i0.ɵɵelementEnd();
26
51
  } if (rf & 2) {
27
- const colRecord_r1 = ctx.$implicit;
52
+ const colRecord_r4 = ctx.$implicit;
28
53
  const ctx_r1 = i0.ɵɵnextContext(3);
29
54
  i0.ɵɵadvance();
30
- i0.ɵɵtextInterpolate(colRecord_r1.Get(ctx_r1.ColumnsEntityDisplayField));
55
+ i0.ɵɵtextInterpolate(colRecord_r4.Get(ctx_r1.ColumnsEntityDisplayField));
31
56
  } }
32
- function JoinGridComponent_Conditional_6_Conditional_5_Template(rf, ctx) { if (rf & 1) {
33
- i0.ɵɵrepeaterCreate(0, JoinGridComponent_Conditional_6_Conditional_5_For_1_Template, 2, 1, "th", null, i0.ɵɵrepeaterTrackByIdentity);
57
+ function JoinGridComponent_Conditional_4_Conditional_5_Template(rf, ctx) { if (rf & 1) {
58
+ i0.ɵɵrepeaterCreate(0, JoinGridComponent_Conditional_4_Conditional_5_For_1_Template, 2, 1, "th", 5, i0.ɵɵrepeaterTrackByIdentity);
34
59
  } if (rf & 2) {
35
60
  const ctx_r1 = i0.ɵɵnextContext(2);
36
61
  i0.ɵɵrepeater(ctx_r1._columnsEntityData);
37
62
  } }
38
- function JoinGridComponent_Conditional_6_Conditional_6_For_1_Template(rf, ctx) { if (rf & 1) {
63
+ function JoinGridComponent_Conditional_4_Conditional_6_For_1_Template(rf, ctx) { if (rf & 1) {
39
64
  i0.ɵɵelementStart(0, "th");
40
65
  i0.ɵɵtext(1);
41
66
  i0.ɵɵelementEnd();
42
67
  } if (rf & 2) {
43
- const colName_r3 = ctx.$implicit;
68
+ const colName_r5 = ctx.$implicit;
44
69
  i0.ɵɵadvance();
45
- i0.ɵɵtextInterpolate(colName_r3);
70
+ i0.ɵɵtextInterpolate(colName_r5);
46
71
  } }
47
- function JoinGridComponent_Conditional_6_Conditional_6_Template(rf, ctx) { if (rf & 1) {
48
- i0.ɵɵrepeaterCreate(0, JoinGridComponent_Conditional_6_Conditional_6_For_1_Template, 2, 1, "th", null, i0.ɵɵrepeaterTrackByIdentity);
72
+ function JoinGridComponent_Conditional_4_Conditional_6_Template(rf, ctx) { if (rf & 1) {
73
+ i0.ɵɵrepeaterCreate(0, JoinGridComponent_Conditional_4_Conditional_6_For_1_Template, 2, 1, "th", null, i0.ɵɵrepeaterTrackByIdentity);
49
74
  } if (rf & 2) {
50
75
  const ctx_r1 = i0.ɵɵnextContext(2);
51
76
  i0.ɵɵrepeater(ctx_r1.JoinEntityDisplayColumns);
52
77
  } }
53
- function JoinGridComponent_Conditional_6_For_9_Conditional_4_td_0_Template(rf, ctx) { if (rf & 1) {
54
- i0.ɵɵelementStart(0, "td");
55
- i0.ɵɵelement(1, "input", 6);
78
+ function JoinGridComponent_Conditional_4_For_9_Conditional_4_Conditional_0_Template(rf, ctx) { if (rf & 1) {
79
+ const _r6 = i0.ɵɵgetCurrentView();
80
+ i0.ɵɵelementStart(0, "button", 9);
81
+ i0.ɵɵlistener("click", function JoinGridComponent_Conditional_4_For_9_Conditional_4_Conditional_0_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const row_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.AddJoinEntityRecord(row_r7)); });
82
+ i0.ɵɵelement(1, "span", 10);
83
+ i0.ɵɵelementEnd();
84
+ } }
85
+ function JoinGridComponent_Conditional_4_For_9_Conditional_4_Conditional_1_Template(rf, ctx) { if (rf & 1) {
86
+ const _r8 = i0.ɵɵgetCurrentView();
87
+ i0.ɵɵelementStart(0, "button", 9);
88
+ i0.ɵɵlistener("click", function JoinGridComponent_Conditional_4_For_9_Conditional_4_Conditional_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const row_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.RemoveJoinEntityRecord(row_r7)); });
89
+ i0.ɵɵelement(1, "span", 11);
90
+ i0.ɵɵelementEnd();
91
+ } }
92
+ function JoinGridComponent_Conditional_4_For_9_Conditional_4_Template(rf, ctx) { if (rf & 1) {
93
+ i0.ɵɵtemplate(0, JoinGridComponent_Conditional_4_For_9_Conditional_4_Conditional_0_Template, 2, 0, "button", 8)(1, JoinGridComponent_Conditional_4_For_9_Conditional_4_Conditional_1_Template, 2, 0, "button", 8);
94
+ } if (rf & 2) {
95
+ const row_r7 = i0.ɵɵnextContext().$implicit;
96
+ i0.ɵɵconditional(!row_r7.JoinExists ? 0 : 1);
97
+ } }
98
+ function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
99
+ const _r9 = i0.ɵɵgetCurrentView();
100
+ i0.ɵɵelementStart(0, "input", 16);
101
+ i0.ɵɵlistener("change", function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_0_Conditional_0_Template_input_change_0_listener($event) { i0.ɵɵrestoreView(_r9); const i_r10 = i0.ɵɵnextContext(4).index; const row_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.UpdateCellValue(row_r7, i_r10, $event)); });
102
+ i0.ɵɵelementEnd();
103
+ } if (rf & 2) {
104
+ const i_r10 = i0.ɵɵnextContext(4).index;
105
+ const row_r7 = i0.ɵɵnextContext(2).$implicit;
106
+ i0.ɵɵproperty("checked", row_r7.GetColumnValue(i_r10));
107
+ } }
108
+ function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
109
+ const _r11 = i0.ɵɵgetCurrentView();
110
+ i0.ɵɵelementStart(0, "kendo-textbox", 17);
111
+ i0.ɵɵlistener("change", function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_0_Conditional_1_Template_kendo_textbox_change_0_listener($event) { i0.ɵɵrestoreView(_r11); const i_r10 = i0.ɵɵnextContext(4).index; const row_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.UpdateCellValue(row_r7, i_r10, $event)); });
112
+ i0.ɵɵelementEnd();
113
+ } if (rf & 2) {
114
+ const i_r10 = i0.ɵɵnextContext(4).index;
115
+ const row_r7 = i0.ɵɵnextContext(2).$implicit;
116
+ i0.ɵɵproperty("value", row_r7.GetColumnValue(i_r10));
117
+ } }
118
+ function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
119
+ i0.ɵɵtemplate(0, JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_0_Conditional_0_Template, 1, 1, "input", 14)(1, JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_0_Conditional_1_Template, 1, 1, "kendo-textbox", 15);
120
+ } if (rf & 2) {
121
+ const colName_r12 = i0.ɵɵnextContext(3).$implicit;
122
+ const ctx_r1 = i0.ɵɵnextContext(4);
123
+ i0.ɵɵconditional(ctx_r1.GetJoinEntityField(colName_r12).TSType === ctx_r1.EntityFieldTSType.Boolean ? 0 : 1);
124
+ } }
125
+ function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
126
+ const _r13 = i0.ɵɵgetCurrentView();
127
+ i0.ɵɵelementStart(0, "kendo-dropdownlist", 18);
128
+ i0.ɵɵlistener("selectionChange", function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_1_Template_kendo_dropdownlist_selectionChange_0_listener($event) { i0.ɵɵrestoreView(_r13); const i_r10 = i0.ɵɵnextContext(3).index; const row_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.UpdateCellValueDirect(row_r7, i_r10, $event)); });
56
129
  i0.ɵɵelementEnd();
130
+ } if (rf & 2) {
131
+ const ctx_r13 = i0.ɵɵnextContext(3);
132
+ const colName_r12 = ctx_r13.$implicit;
133
+ const i_r10 = ctx_r13.index;
134
+ const row_r7 = i0.ɵɵnextContext(2).$implicit;
135
+ const ctx_r1 = i0.ɵɵnextContext(2);
136
+ i0.ɵɵproperty("data", ctx_r1.GetJoinEntityFieldValues(colName_r12))("value", row_r7.GetColumnValue(i_r10));
137
+ } }
138
+ function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
139
+ i0.ɵɵtemplate(0, JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_0_Template, 2, 1)(1, JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Conditional_1_Template, 1, 2, "kendo-dropdownlist", 13);
140
+ } if (rf & 2) {
141
+ const colName_r12 = i0.ɵɵnextContext(2).$implicit;
142
+ const ctx_r1 = i0.ɵɵnextContext(4);
143
+ i0.ɵɵconditional(ctx_r1.GetJoinEntityField(colName_r12).ValueListType === "None" ? 0 : 1);
57
144
  } }
58
- function JoinGridComponent_Conditional_6_For_9_Conditional_4_Template(rf, ctx) { if (rf & 1) {
59
- i0.ɵɵtemplate(0, JoinGridComponent_Conditional_6_For_9_Conditional_4_td_0_Template, 2, 0, "td", 5);
145
+ function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
146
+ i0.ɵɵtemplate(0, JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Conditional_0_Template, 2, 1);
147
+ } if (rf & 2) {
148
+ const row_r7 = i0.ɵɵnextContext(3).$implicit;
149
+ i0.ɵɵconditional(row_r7.JoinExists ? 0 : -1);
150
+ } }
151
+ function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_2_Template(rf, ctx) { if (rf & 1) {
152
+ i0.ɵɵtext(0);
153
+ } if (rf & 2) {
154
+ const i_r10 = i0.ɵɵnextContext().index;
155
+ const row_r7 = i0.ɵɵnextContext(2).$implicit;
156
+ i0.ɵɵtextInterpolate1(" ", row_r7.GetColumnValue(i_r10), " ");
157
+ } }
158
+ function JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Template(rf, ctx) { if (rf & 1) {
159
+ i0.ɵɵelementStart(0, "td", 7);
160
+ i0.ɵɵtemplate(1, JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_1_Template, 1, 1)(2, JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Conditional_2_Template, 1, 1);
161
+ i0.ɵɵelementEnd();
162
+ } if (rf & 2) {
163
+ const ctx_r1 = i0.ɵɵnextContext(4);
164
+ i0.ɵɵadvance();
165
+ i0.ɵɵconditional(ctx_r1.EditMode !== "None" ? 1 : 2);
166
+ } }
167
+ function JoinGridComponent_Conditional_4_For_9_Conditional_5_Template(rf, ctx) { if (rf & 1) {
168
+ i0.ɵɵtemplate(0, JoinGridComponent_Conditional_4_For_9_Conditional_5_td_0_Template, 3, 1, "td", 12);
60
169
  } if (rf & 2) {
61
170
  const ctx_r1 = i0.ɵɵnextContext(3);
62
171
  i0.ɵɵproperty("ngForOf", ctx_r1.JoinEntityDisplayColumns);
63
172
  } }
64
- function JoinGridComponent_Conditional_6_For_9_Conditional_5_For_1_Template(rf, ctx) { if (rf & 1) {
65
- const _r4 = i0.ɵɵgetCurrentView();
66
- i0.ɵɵelementStart(0, "td", 7);
67
- i0.ɵɵlistener("click", function JoinGridComponent_Conditional_6_For_9_Conditional_5_For_1_Template_td_click_0_listener($event) { const cell_r5 = i0.ɵɵrestoreView(_r4).$implicit; const row_r6 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1._FlipRecord($event, row_r6, cell_r5)); });
68
- i0.ɵɵelementStart(1, "input", 8);
69
- i0.ɵɵlistener("click", function JoinGridComponent_Conditional_6_For_9_Conditional_5_For_1_Template_input_click_1_listener($event) { const cell_r5 = i0.ɵɵrestoreView(_r4).$implicit; const row_r6 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1._FlipRecord($event, row_r6, cell_r5, true)); });
70
- i0.ɵɵelementEnd()();
173
+ function JoinGridComponent_Conditional_4_For_9_Conditional_6_For_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
174
+ const _r17 = i0.ɵɵgetCurrentView();
175
+ i0.ɵɵelementStart(0, "input", 22);
176
+ i0.ɵɵlistener("click", function JoinGridComponent_Conditional_4_For_9_Conditional_6_For_1_Conditional_1_Template_input_click_0_listener($event) { i0.ɵɵrestoreView(_r17); const cell_r16 = i0.ɵɵnextContext().$implicit; const row_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1._FlipRecord($event, row_r7, cell_r16, true)); });
177
+ i0.ɵɵelementEnd();
178
+ } if (rf & 2) {
179
+ const cell_r16 = i0.ɵɵnextContext().$implicit;
180
+ const ctx_r1 = i0.ɵɵnextContext(4);
181
+ i0.ɵɵproperty("checked", ctx_r1._IsColumnChecked(cell_r16));
182
+ } }
183
+ function JoinGridComponent_Conditional_4_For_9_Conditional_6_For_1_Conditional_2_Template(rf, ctx) { if (rf & 1) {
184
+ i0.ɵɵtext(0);
185
+ } if (rf & 2) {
186
+ const cell_r16 = i0.ɵɵnextContext().$implicit;
187
+ i0.ɵɵtextInterpolate1(" ", cell_r16.value ? "\u2713" : "", " ");
188
+ } }
189
+ function JoinGridComponent_Conditional_4_For_9_Conditional_6_For_1_Template(rf, ctx) { if (rf & 1) {
190
+ const _r15 = i0.ɵɵgetCurrentView();
191
+ i0.ɵɵelementStart(0, "td", 20);
192
+ i0.ɵɵlistener("click", function JoinGridComponent_Conditional_4_For_9_Conditional_6_For_1_Template_td_click_0_listener($event) { const cell_r16 = i0.ɵɵrestoreView(_r15).$implicit; const row_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1._FlipRecord($event, row_r7, cell_r16)); });
193
+ i0.ɵɵtemplate(1, JoinGridComponent_Conditional_4_For_9_Conditional_6_For_1_Conditional_1_Template, 1, 1, "input", 21)(2, JoinGridComponent_Conditional_4_For_9_Conditional_6_For_1_Conditional_2_Template, 1, 1);
194
+ i0.ɵɵelementEnd();
71
195
  } if (rf & 2) {
72
- const cell_r5 = ctx.$implicit;
196
+ const cell_r16 = ctx.$implicit;
73
197
  const ctx_r1 = i0.ɵɵnextContext(4);
74
- i0.ɵɵproperty("ngClass", ctx_r1.IsCellReallyDirty(cell_r5) ? "dirty-cell" : "");
198
+ i0.ɵɵproperty("ngClass", ctx_r1.IsCellReallyDirty(cell_r16) ? "dirty-cell" : "");
75
199
  i0.ɵɵadvance();
76
- i0.ɵɵproperty("checked", ctx_r1._IsColumnChecked(cell_r5));
200
+ i0.ɵɵconditional(ctx_r1.EditMode !== "None" ? 1 : 2);
77
201
  } }
78
- function JoinGridComponent_Conditional_6_For_9_Conditional_5_Template(rf, ctx) { if (rf & 1) {
79
- i0.ɵɵrepeaterCreate(0, JoinGridComponent_Conditional_6_For_9_Conditional_5_For_1_Template, 2, 2, "td", 3, i0.ɵɵrepeaterTrackByIdentity);
202
+ function JoinGridComponent_Conditional_4_For_9_Conditional_6_Template(rf, ctx) { if (rf & 1) {
203
+ i0.ɵɵrepeaterCreate(0, JoinGridComponent_Conditional_4_For_9_Conditional_6_For_1_Template, 3, 2, "td", 19, i0.ɵɵrepeaterTrackByIdentity);
80
204
  } if (rf & 2) {
81
- const row_r6 = i0.ɵɵnextContext().$implicit;
82
- i0.ɵɵrepeater(row_r6.ColumnData);
205
+ const row_r7 = i0.ɵɵnextContext().$implicit;
206
+ i0.ɵɵrepeater(row_r7.ColumnData);
83
207
  } }
84
- function JoinGridComponent_Conditional_6_For_9_Template(rf, ctx) { if (rf & 1) {
85
- i0.ɵɵelementStart(0, "tr", 3)(1, "td", 4)(2, "span");
208
+ function JoinGridComponent_Conditional_4_For_9_Template(rf, ctx) { if (rf & 1) {
209
+ i0.ɵɵelementStart(0, "tr", 4)(1, "td", 6)(2, "span");
86
210
  i0.ɵɵtext(3);
87
- i0.ɵɵelementEnd()();
88
- i0.ɵɵtemplate(4, JoinGridComponent_Conditional_6_For_9_Conditional_4_Template, 1, 1, "td")(5, JoinGridComponent_Conditional_6_For_9_Conditional_5_Template, 2, 0);
211
+ i0.ɵɵelementEnd();
212
+ i0.ɵɵtemplate(4, JoinGridComponent_Conditional_4_For_9_Conditional_4_Template, 2, 1);
213
+ i0.ɵɵelementEnd();
214
+ i0.ɵɵtemplate(5, JoinGridComponent_Conditional_4_For_9_Conditional_5_Template, 1, 1, "td", 7)(6, JoinGridComponent_Conditional_4_For_9_Conditional_6_Template, 2, 0);
89
215
  i0.ɵɵelementEnd();
90
216
  } if (rf & 2) {
91
- const row_r6 = ctx.$implicit;
217
+ const row_r7 = ctx.$implicit;
92
218
  const ctx_r1 = i0.ɵɵnextContext(2);
93
- i0.ɵɵproperty("ngClass", ctx_r1.IsRecordReallyDirty(row_r6) ? "dirty-row" : "");
219
+ i0.ɵɵproperty("ngClass", ctx_r1.IsRecordReallyDirty(row_r7) ? "dirty-row" : "");
94
220
  i0.ɵɵadvance(3);
95
- i0.ɵɵtextInterpolate(row_r6.FirstColValue);
221
+ i0.ɵɵtextInterpolate(row_r7.FirstColValue);
96
222
  i0.ɵɵadvance();
97
- i0.ɵɵconditional(ctx_r1.ColumnsMode === "Fields" ? 4 : 5);
223
+ i0.ɵɵconditional(ctx_r1.EditMode !== "None" ? 4 : -1);
224
+ i0.ɵɵadvance();
225
+ i0.ɵɵconditional(ctx_r1.ColumnsMode === "Fields" ? 5 : 6);
98
226
  } }
99
- function JoinGridComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
227
+ function JoinGridComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
100
228
  i0.ɵɵelementStart(0, "table", 2)(1, "thead")(2, "tr")(3, "th");
101
229
  i0.ɵɵtext(4);
102
230
  i0.ɵɵelementEnd();
103
- i0.ɵɵtemplate(5, JoinGridComponent_Conditional_6_Conditional_5_Template, 2, 0)(6, JoinGridComponent_Conditional_6_Conditional_6_Template, 2, 0);
231
+ i0.ɵɵtemplate(5, JoinGridComponent_Conditional_4_Conditional_5_Template, 2, 0)(6, JoinGridComponent_Conditional_4_Conditional_6_Template, 2, 0);
104
232
  i0.ɵɵelementEnd()();
105
233
  i0.ɵɵelementStart(7, "tbody");
106
- i0.ɵɵrepeaterCreate(8, JoinGridComponent_Conditional_6_For_9_Template, 6, 3, "tr", 3, i0.ɵɵrepeaterTrackByIdentity);
234
+ i0.ɵɵrepeaterCreate(8, JoinGridComponent_Conditional_4_For_9_Template, 7, 4, "tr", 4, i0.ɵɵrepeaterTrackByIdentity);
107
235
  i0.ɵɵelementEnd()();
108
236
  } if (rf & 2) {
109
237
  const ctx_r1 = i0.ɵɵnextContext();
110
238
  i0.ɵɵadvance(4);
111
- i0.ɵɵtextInterpolate(ctx_r1.RowsEntityName);
239
+ i0.ɵɵtextInterpolate(ctx_r1.RowsEntityDisplayNameOrName);
112
240
  i0.ɵɵadvance();
113
241
  i0.ɵɵconditional(ctx_r1.ColumnsMode === "Entity" ? 5 : 6);
114
242
  i0.ɵɵadvance(3);
@@ -117,18 +245,25 @@ function JoinGridComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
117
245
  export class JoinGridCell {
118
246
  }
119
247
  export class JoinGridRow {
120
- constructor() {
248
+ GetColumnValue(colIndex) {
249
+ return this.ColumnData && this.ColumnData.length > colIndex ? this.ColumnData[colIndex].value : undefined;
250
+ }
251
+ constructor(data) {
121
252
  this.JoinExists = false;
122
253
  this.ColumnData = [];
254
+ this.FirstColValue = data.FirstColValue;
255
+ this.JoinExists = data.JoinExists;
256
+ this.RowForeignKeyValue = data.RowForeignKeyValue;
257
+ this.ColumnData = data.ColumnData;
123
258
  }
124
259
  }
125
260
  export class JoinGridComponent {
126
- ngAfterViewInit() {
127
- // load up the grid
128
- this.Refresh();
261
+ get RowsEntityDisplayNameOrName() {
262
+ return this.RowsEntityDisplayName ? this.RowsEntityDisplayName : this.RowsEntityName;
129
263
  }
130
- constructor(cdr) {
264
+ constructor(cdr, elementRef) {
131
265
  this.cdr = cdr;
266
+ this.elementRef = elementRef;
132
267
  /**
133
268
  * Determines how the row data will be fetched.
134
269
  * * When set to FullEntity, all rows in the specified RowEntityName will be used.
@@ -148,6 +283,7 @@ export class JoinGridComponent {
148
283
  */
149
284
  this.ColumnsEntityDataSource = 'FullEntity';
150
285
  /**
286
+ * ONLY USED WHEN ColumnsMode=Entity
151
287
  * When this property is set to JoinRecordExists the grid will operate as follows:
152
288
  * * When a user checks the checkbox in the grid, a record will be created in the JoinEntity with the Row and Column foreign keys.
153
289
  * * When a user unchecks the checkbox in the grid, the record in the JoinEntity will be deleted.
@@ -156,6 +292,19 @@ export class JoinGridComponent {
156
292
  * * When a user unchecks the checkbox in the grid, the value in the JoinEntity will be set to false in the CheckBoxValueField field.
157
293
  */
158
294
  this.CheckBoxValueMode = 'RecordExists';
295
+ /**
296
+ * When set to true, the Save button is shown
297
+ */
298
+ this.ShowSaveButton = true;
299
+ /**
300
+ * When set to true, the Cancel button is shown
301
+ */
302
+ this.ShowCancelButton = true;
303
+ /**
304
+ * Change the value of this property to true or false when you want to enter or exit edit mode. Only use this when the grid
305
+ * is embedded in another form and you are not showing the built-in save/cancel buttons
306
+ */
307
+ this.EditMode = 'None';
159
308
  /*The below members are public because the Angular template needs access to them, but by naming convention we prefix with an _ so that it is clear they are not to be used outside of the component */
160
309
  this._GridData = [];
161
310
  this._IsLoading = false;
@@ -164,6 +313,7 @@ export class JoinGridComponent {
164
313
  this._columnsEntityInfo = null;
165
314
  this._columnsEntityData = undefined;
166
315
  this._rowsEntityData = undefined;
316
+ this._joinEntityData = undefined;
167
317
  this._pendingDeletes = [];
168
318
  this._pendingInserts = [];
169
319
  }
@@ -172,38 +322,70 @@ export class JoinGridComponent {
172
322
  */
173
323
  Save() {
174
324
  return __awaiter(this, void 0, void 0, function* () {
325
+ var _a;
175
326
  // for each pending delete, we need to delete the record
176
327
  // for each pending insert, we need to save the record
177
328
  // do it all in one transaction
178
329
  const md = new Metadata();
179
330
  const tg = yield md.CreateTransactionGroup();
180
- let validated = true;
181
- const valErrors = [];
182
- this._pendingDeletes.forEach(obj => {
183
- obj.TransactionGroup = tg;
184
- obj.Delete();
185
- });
186
- this._pendingInserts.forEach(obj => {
187
- obj.TransactionGroup = tg;
188
- const valResult = obj.Validate();
189
- validated = validated && valResult.Success;
190
- valErrors.push(valResult.Errors);
191
- obj.Save();
192
- });
193
- if (validated) {
194
- if (!(yield tg.Submit())) {
195
- alert('Error saving changes');
196
- return false;
331
+ if (this.ColumnsMode === 'Entity') {
332
+ let validated = true;
333
+ const valErrors = [];
334
+ this._pendingDeletes.forEach(obj => {
335
+ obj.TransactionGroup = tg;
336
+ obj.Delete();
337
+ });
338
+ this._pendingInserts.forEach(obj => {
339
+ obj.TransactionGroup = tg;
340
+ const valResult = obj.Validate();
341
+ validated = validated && valResult.Success;
342
+ valErrors.push(valResult.Errors);
343
+ obj.Save();
344
+ });
345
+ if (validated) {
346
+ if (!(yield tg.Submit())) {
347
+ alert('Error saving changes');
348
+ return false;
349
+ }
350
+ else {
351
+ yield this.Refresh(); // refresh afterwards
352
+ return true;
353
+ }
197
354
  }
198
355
  else {
199
- yield this.Refresh(); // refresh afterwards
200
- return true;
356
+ alert('Error validating changes, details in console');
357
+ console.log(valErrors);
358
+ return false;
201
359
  }
202
360
  }
203
361
  else {
204
- alert('Error validating changes, details in console');
205
- console.log(valErrors);
206
- return false;
362
+ // in fields mode we use the _joinEntityData array to save the changes
363
+ let validated = true;
364
+ const valErrors = [];
365
+ (_a = this._joinEntityData) === null || _a === void 0 ? void 0 : _a.forEach(obj => {
366
+ if (obj.Dirty) {
367
+ obj.TransactionGroup = tg;
368
+ const valResult = obj.Validate();
369
+ validated = validated && valResult.Success;
370
+ valErrors.push(valResult.Errors);
371
+ obj.Save();
372
+ }
373
+ });
374
+ if (validated) {
375
+ if (!(yield tg.Submit())) {
376
+ alert('Error saving changes');
377
+ return false;
378
+ }
379
+ else {
380
+ yield this.Refresh(); // refresh afterwards
381
+ return true;
382
+ }
383
+ }
384
+ else {
385
+ alert('Error validating changes, details in console');
386
+ console.log(valErrors);
387
+ return false;
388
+ }
207
389
  }
208
390
  });
209
391
  }
@@ -268,21 +450,27 @@ export class JoinGridComponent {
268
450
  this.cdr.detectChanges(); // let angular know we have changes
269
451
  this._pendingDeletes = [];
270
452
  this._pendingInserts = [];
453
+ this._joinEntityData = undefined;
271
454
  // we are provided an array of Column and Row objects. We need to get the rows from the JoinEntity that link them up.
272
455
  const md = new Metadata();
456
+ if (this.ColumnsMode === 'Entity') {
457
+ this._columnsEntityInfo = md.EntityByName(this.ColumnsEntityName);
458
+ if (!this._columnsEntityInfo)
459
+ throw new Error('Invalid entity name provided for columns entity.');
460
+ }
273
461
  this._rowsEntityInfo = md.EntityByName(this.RowsEntityName);
274
- this._columnsEntityInfo = md.EntityByName(this.ColumnsEntityName);
275
462
  if (!this._rowsEntityInfo)
276
463
  throw new Error('Invalid entity name provided for rows entity.');
277
- if (!this._columnsEntityInfo)
278
- throw new Error('Invalid entity name provided for columns entity.');
279
464
  yield this.PopulateRowsAndColsData();
280
465
  const rowQuotes = this._rowsEntityInfo.FirstPrimaryKey.NeedsQuotes ? "'" : "";
281
466
  let filter = `${this.JoinEntityRowForeignKey} IN (${this._rowsEntityData.map(obj => `${rowQuotes}${obj.Get(this._rowsEntityInfo.FirstPrimaryKey.Name)}${rowQuotes}`).join(',')})`;
282
- if (this.ColumnsMode === 'Entity') {
467
+ if (this.ColumnsMode === 'Entity' && this._columnsEntityInfo) {
283
468
  const colQuotes = this._columnsEntityInfo.FirstPrimaryKey.NeedsQuotes ? "'" : "";
284
469
  filter += ` AND ${this.JoinEntityColumnForeignKey} IN (${this._columnsEntityData.map(obj => `${colQuotes}${obj.Get(this._columnsEntityInfo.FirstPrimaryKey.Name)}${colQuotes}`).join(',')})`;
285
470
  }
471
+ if (this.JoinEntityExtraFilter) {
472
+ filter = `(${filter}) AND (${this.JoinEntityExtraFilter})`;
473
+ }
286
474
  const rv = new RunView();
287
475
  const result = yield rv.RunView({
288
476
  EntityName: this.JoinEntityName,
@@ -291,7 +479,8 @@ export class JoinGridComponent {
291
479
  });
292
480
  if (result && result.Success) {
293
481
  // we have the data, now we need to build the grid
294
- this.PopulateGridData(result.Results);
482
+ this._joinEntityData = result.Results;
483
+ this.PopulateGridData();
295
484
  }
296
485
  this._IsLoading = false; // turn off the loading spinner
297
486
  this.cdr.detectChanges(); // let Angular know we have changes
@@ -300,11 +489,14 @@ export class JoinGridComponent {
300
489
  PopulateRowsAndColsData() {
301
490
  return __awaiter(this, void 0, void 0, function* () {
302
491
  const rv = new RunView();
303
- if (this.ColumnsEntityDataSource === 'Array') {
304
- this._columnsEntityData = this.ColumnsEntityArray;
305
- }
306
- else {
307
- this._columnsEntityData = yield this.RunColumnsOrRowsView(this.ColumnsEntityDataSource, this.ColumnsEntityName, this.ColumnsEntityViewName, this.ColumnsExtraFilter, this.ColumnsOrderBy);
492
+ if (this.ColumnsMode === 'Entity') {
493
+ // only populate the columns if we are using the entity mode, otherwise the array from JoinGridDisplayColumns will be used
494
+ if (this.ColumnsEntityDataSource === 'Array') {
495
+ this._columnsEntityData = this.ColumnsEntityArray;
496
+ }
497
+ else {
498
+ this._columnsEntityData = yield this.RunColumnsOrRowsView(this.ColumnsEntityDataSource, this.ColumnsEntityName, this.ColumnsEntityViewName, this.ColumnsExtraFilter, this.ColumnsOrderBy);
499
+ }
308
500
  }
309
501
  if (this.RowsEntityDataSource === 'Array') {
310
502
  this._rowsEntityData = this.RowsEntityArray;
@@ -332,24 +524,27 @@ export class JoinGridComponent {
332
524
  }
333
525
  });
334
526
  }
335
- PopulateGridData(joinEntityData) {
527
+ PopulateGridData() {
336
528
  return __awaiter(this, void 0, void 0, function* () {
337
529
  // we have the data, now we need to build the grid
338
530
  // we need to build the grid data
531
+ if (!this._joinEntityData)
532
+ throw new Error('_joinEntityData must be populated before calling PopulateGridData()');
339
533
  const gridData = [];
340
- this._rowsEntityData.forEach(row => {
341
- let rowData = {
534
+ this._rowsEntityData.forEach((row, rowIndex) => {
535
+ let rowData = new JoinGridRow({
342
536
  FirstColValue: row.Get(this.RowsEntityDisplayField),
343
537
  JoinExists: false,
344
538
  RowForeignKeyValue: row.Get(this._rowsEntityInfo.FirstPrimaryKey.Name),
345
539
  ColumnData: [] // start off with an empty array
346
- };
540
+ });
347
541
  // for the mode where we are using columns, do the following
348
542
  if (this.ColumnsMode === 'Entity') {
349
543
  for (let i = 0; i < this._columnsEntityData.length; i++) {
350
544
  const column = this._columnsEntityData[i];
351
- const join = joinEntityData.find(j => j.Get(this.JoinEntityRowForeignKey) === row.Get(this._rowsEntityInfo.FirstPrimaryKey.Name) &&
545
+ const join = this._joinEntityData.find(j => j.Get(this.JoinEntityRowForeignKey) === row.Get(this._rowsEntityInfo.FirstPrimaryKey.Name) &&
352
546
  j.Get(this.JoinEntityColumnForeignKey) === column.Get(this._columnsEntityInfo.FirstPrimaryKey.Name));
547
+ rowData.JoinExists = true;
353
548
  rowData.ColumnData.push({
354
549
  index: i,
355
550
  ColumnForeignKeyValue: column.Get(this._columnsEntityInfo.FirstPrimaryKey.Name),
@@ -359,7 +554,21 @@ export class JoinGridComponent {
359
554
  }
360
555
  }
361
556
  else {
557
+ if (!this.JoinEntityDisplayColumns)
558
+ throw new Error('JoinEntityDisplayColumns is required when ColumnsMode is set to Fields');
362
559
  // we are display the values from the JoinEntity as columns from the JoinEntityDisplayColumns array
560
+ this.JoinEntityDisplayColumns.forEach((col, i) => {
561
+ const joinData = this._joinEntityData.find(jed => jed.Get(this.JoinEntityRowForeignKey) === row.FirstPrimaryKey.Value);
562
+ // joinData being undefined/null is a valid condition just means no join data for the row specified
563
+ if (joinData) {
564
+ rowData.JoinExists = true;
565
+ rowData.ColumnData.push({
566
+ index: i,
567
+ RowForeignKeyValue: rowData.RowForeignKeyValue,
568
+ value: joinData.Get(col)
569
+ });
570
+ }
571
+ });
363
572
  }
364
573
  gridData.push(rowData);
365
574
  });
@@ -407,35 +616,185 @@ export class JoinGridComponent {
407
616
  _IsColumnChecked(cell) {
408
617
  return (cell === null || cell === void 0 ? void 0 : cell.data) !== undefined;
409
618
  }
619
+ UpdateCellValueDirect(row, colIndex, newValue) {
620
+ return __awaiter(this, void 0, void 0, function* () {
621
+ // find the associated baseEntity object and update the value and then refresh the grid state from it
622
+ if (this.ColumnsMode !== 'Fields')
623
+ throw new Error("This method should only be called when ColumnsMode=Entity");
624
+ // we are good now, so now proceed to find the related object that ties to the rowForeignKey in
625
+ // the join entity data array
626
+ const joinData = this._joinEntityData.find(jed => jed.Get(this.JoinEntityRowForeignKey) === row.RowForeignKeyValue);
627
+ if (!joinData)
628
+ LogError('Could not find join data for rowForeignKey ' + row.RowForeignKeyValue);
629
+ else {
630
+ const colName = this.JoinEntityDisplayColumns[colIndex];
631
+ joinData.Set(colName, newValue);
632
+ // also update the row's column array
633
+ row.ColumnData[colIndex].value = joinData.Get(colName);
634
+ }
635
+ });
636
+ }
637
+ UpdateCellValue(row, colIndex, event) {
638
+ return __awaiter(this, void 0, void 0, function* () {
639
+ this.UpdateCellValueDirect(row, colIndex, event.target.value);
640
+ });
641
+ }
642
+ /**
643
+ * Only used when ColumnsMode = Fields
644
+ * @param row
645
+ */
646
+ RemoveJoinEntityRecord(row) {
647
+ return __awaiter(this, void 0, void 0, function* () {
648
+ var _a;
649
+ // this method is called when the user wnats to remove a record that maps to the cell for the row specified and the colIndex
650
+ // only used when Mode = Fields
651
+ if (this.ColumnsMode !== 'Fields')
652
+ throw new Error('This method should only be called when ColumnsMode=Entity');
653
+ const joinData = this._joinEntityData.find(jed => jed.Get(this.JoinEntityRowForeignKey) === row.RowForeignKeyValue);
654
+ if (!joinData)
655
+ LogError('Could not find join data for rowForeignKey ' + row.RowForeignKeyValue);
656
+ else {
657
+ this._pendingDeletes.push(joinData);
658
+ (_a = this._joinEntityData) === null || _a === void 0 ? void 0 : _a.splice(this._joinEntityData.indexOf(joinData), 1);
659
+ this.PopulateGridData(); // refresh the grid's grid data array that is derived from all of the source data
660
+ }
661
+ });
662
+ }
663
+ /**
664
+ * Only used when ColumnsMode = Fields
665
+ */
666
+ AddJoinEntityRecord(row) {
667
+ return __awaiter(this, void 0, void 0, function* () {
668
+ var _a;
669
+ // this method is called when the user wnats to create a new record that maps to the cell for the row specified and the colIndex
670
+ // only used when Mode = Fields
671
+ if (this.ColumnsMode !== 'Fields')
672
+ throw new Error('This method should only be called when ColumnsMode=Entity');
673
+ const md = new Metadata();
674
+ // first check to see if this is in the _pendingDeletes array, if so, we need to remove it from there
675
+ let newObj = this._pendingDeletes.find(pd => pd.Get(this.JoinEntityRowForeignKey) === row.RowForeignKeyValue);
676
+ if (newObj) {
677
+ this._pendingDeletes.splice(this._pendingDeletes.indexOf(newObj), 1);
678
+ }
679
+ else {
680
+ newObj = yield md.GetEntityObject(this.JoinEntityName);
681
+ newObj.Set(this.JoinEntityRowForeignKey, row.RowForeignKeyValue);
682
+ }
683
+ const keys = this.NewRecordDefaultValues ? Object.keys(this.NewRecordDefaultValues) : [];
684
+ for (const k of keys) {
685
+ newObj.Set(k, this.NewRecordDefaultValues[k]);
686
+ }
687
+ (_a = this._joinEntityData) === null || _a === void 0 ? void 0 : _a.push(newObj); // add to join data array
688
+ if (this.EditMode === 'Save') {
689
+ if (yield newObj.Save()) {
690
+ // all good
691
+ }
692
+ else {
693
+ SharedService.Instance.CreateSimpleNotification('Error saving new ' + this.JoinEntityName + ' record', 'error', 2500);
694
+ }
695
+ }
696
+ this.PopulateGridData(); // refresh the grid's grid data array that is derived from all of the source data
697
+ });
698
+ }
699
+ EditingComplete() {
700
+ return __awaiter(this, void 0, void 0, function* () {
701
+ // we've been told that editing is done. If we are in queue mode for editing, we do nothing because we've
702
+ // already submitted our pending changes via events (below) but if we're in save mode we save stuff now
703
+ if (this.EditMode === 'Save') {
704
+ yield this.Save();
705
+ }
706
+ });
707
+ }
708
+ RevertPendingChanges() {
709
+ return __awaiter(this, void 0, void 0, function* () {
710
+ // this method means we should revert back to the last saved state
711
+ // so just call Refresh
712
+ yield this.Refresh();
713
+ });
714
+ }
715
+ ngAfterViewInit() {
716
+ this.Refresh();
717
+ // setup event listener for MJGlobal because we might have a parent component that sends us messages
718
+ MJGlobal.Instance.GetEventListener(false).subscribe((e) => {
719
+ var _a;
720
+ switch (e.event) {
721
+ case MJEventType.ComponentEvent:
722
+ const b = BaseFormComponentEventCodes; // having issues using the const vs the type if we refer to it below directly for comparison so assign the const to a local variable first
723
+ if (e.eventCode === b.BASE_CODE) {
724
+ // we have an event from a BaseFormComponent, now we need to determine if WE are a descendant of that component
725
+ const event = e.args;
726
+ if (SharedService.IsDescendant(event.elementRef, this.elementRef)) {
727
+ // we are a descendant of the component that sent the event, so we need to handle it
728
+ switch (event.subEventCode) {
729
+ case b.EDITING_COMPLETE:
730
+ this.EditingComplete();
731
+ break;
732
+ case b.REVERT_PENDING_CHANGES:
733
+ this.RevertPendingChanges();
734
+ break;
735
+ case b.POPULATE_PENDING_RECORDS:
736
+ // provide all of our pending records back to the caller
737
+ (_a = this._joinEntityData) === null || _a === void 0 ? void 0 : _a.forEach((r) => {
738
+ // for anything that's changed, we need to add it to the pending records
739
+ const editingEvent = event;
740
+ if (r.Dirty) {
741
+ editingEvent.pendingChanges.push({ entityObject: r, action: 'save' });
742
+ }
743
+ });
744
+ this._pendingDeletes.forEach((r) => {
745
+ const editingEvent = event;
746
+ editingEvent.pendingChanges.push({ entityObject: r, action: 'delete' });
747
+ });
748
+ break;
749
+ }
750
+ }
751
+ }
752
+ break;
753
+ }
754
+ });
755
+ }
756
+ /**
757
+ * Returns the EntityFieldInfo that matches the specific column name within the JoinEntity
758
+ * @param colName
759
+ */
760
+ GetJoinEntityField(colName) {
761
+ const md = new Metadata();
762
+ const entity = md.EntityByName(this.JoinEntityName);
763
+ if (!entity)
764
+ throw new Error('Invalid entity name provided for JoinEntity');
765
+ const field = entity.Fields.find(f => f.Name === colName);
766
+ if (!field)
767
+ throw new Error('Invalid field name provided for JoinEntity');
768
+ return field;
769
+ }
770
+ GetJoinEntityFieldValues(colName) {
771
+ return this.GetJoinEntityField(colName).EntityFieldValues.map(efv => efv.Value);
772
+ }
773
+ get EntityFieldTSType() {
774
+ return EntityFieldTSType;
775
+ }
410
776
  }
411
- JoinGridComponent.ɵfac = function JoinGridComponent_Factory(t) { return new (t || JoinGridComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
412
- JoinGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: JoinGridComponent, selectors: [["mj-join-grid"]], inputs: { RowsEntityName: "RowsEntityName", RowsEntityDisplayField: "RowsEntityDisplayField", RowsEntityDataSource: "RowsEntityDataSource", RowsExtraFilter: "RowsExtraFilter", RowsOrderBy: "RowsOrderBy", RowsEntityViewName: "RowsEntityViewName", RowsEntityArray: "RowsEntityArray", ColumnsMode: "ColumnsMode", ColumnsEntityName: "ColumnsEntityName", ColumnsEntityDisplayField: "ColumnsEntityDisplayField", ColumnsEntityDataSource: "ColumnsEntityDataSource", ColumnsExtraFilter: "ColumnsExtraFilter", ColumnsOrderBy: "ColumnsOrderBy", ColumnsEntityViewName: "ColumnsEntityViewName", ColumnsEntityArray: "ColumnsEntityArray", JoinEntityName: "JoinEntityName", JoinEntityRowForeignKey: "JoinEntityRowForeignKey", JoinEntityColumnForeignKey: "JoinEntityColumnForeignKey", JoinEntityDisplayColumns: "JoinEntityDisplayColumns", CheckBoxValueMode: "CheckBoxValueMode", CheckBoxValueField: "CheckBoxValueField", NewRecordDefaultValues: "NewRecordDefaultValues" }, decls: 7, vars: 4, consts: [["mjFillContainer", "", 1, "wrapper"], ["kendoButton", "", 3, "click", "disabled"], [1, "grid"], [3, "ngClass"], [1, "first-column"], [4, "ngFor", "ngForOf"], ["type", "checkbox", "kendoCheckBox", ""], [3, "click", "ngClass"], ["type", "checkbox", "kendoCheckBox", "", 3, "click", "checked"]], template: function JoinGridComponent_Template(rf, ctx) { if (rf & 1) {
777
+ JoinGridComponent.ɵfac = function JoinGridComponent_Factory(t) { return new (t || JoinGridComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ElementRef)); };
778
+ JoinGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: JoinGridComponent, selectors: [["mj-join-grid"]], inputs: { RowsEntityName: "RowsEntityName", RowsEntityDisplayName: "RowsEntityDisplayName", RowsEntityDisplayField: "RowsEntityDisplayField", RowsEntityDataSource: "RowsEntityDataSource", RowsExtraFilter: "RowsExtraFilter", RowsOrderBy: "RowsOrderBy", RowsEntityViewName: "RowsEntityViewName", RowsEntityArray: "RowsEntityArray", ColumnsMode: "ColumnsMode", ColumnsEntityName: "ColumnsEntityName", ColumnsEntityDisplayField: "ColumnsEntityDisplayField", ColumnsEntityDataSource: "ColumnsEntityDataSource", ColumnsExtraFilter: "ColumnsExtraFilter", ColumnsOrderBy: "ColumnsOrderBy", ColumnsEntityViewName: "ColumnsEntityViewName", ColumnsEntityArray: "ColumnsEntityArray", JoinEntityName: "JoinEntityName", JoinEntityRowForeignKey: "JoinEntityRowForeignKey", JoinEntityColumnForeignKey: "JoinEntityColumnForeignKey", JoinEntityDisplayColumns: "JoinEntityDisplayColumns", JoinEntityExtraFilter: "JoinEntityExtraFilter", CheckBoxValueMode: "CheckBoxValueMode", CheckBoxValueField: "CheckBoxValueField", NewRecordDefaultValues: "NewRecordDefaultValues", ShowSaveButton: "ShowSaveButton", ShowCancelButton: "ShowCancelButton", EditMode: "EditMode" }, decls: 5, vars: 4, consts: [["mjFillContainer", "", 1, "wrapper"], ["kendoButton", "", 3, "disabled"], [1, "grid"], ["kendoButton", "", 3, "click", "disabled"], [3, "ngClass"], [1, "checkbox-column"], [1, "first-column"], [1, "column-cell"], ["kendoButton", "", 1, "cellButton"], ["kendoButton", "", 1, "cellButton", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "fa-solid", "fa-minus"], ["class", "column-cell", 4, "ngFor", "ngForOf"], [3, "data", "value"], ["type", "checkbox", 3, "checked"], [3, "value"], ["type", "checkbox", 3, "change", "checked"], [3, "change", "value"], [3, "selectionChange", "data", "value"], [1, "checkbox-column", 3, "ngClass"], [1, "checkbox-column", 3, "click", "ngClass"], ["type", "checkbox", "kendoCheckBox", "", 3, "checked"], ["type", "checkbox", "kendoCheckBox", "", 3, "click", "checked"]], template: function JoinGridComponent_Template(rf, ctx) { if (rf & 1) {
413
779
  i0.ɵɵelementStart(0, "div", 0);
414
- i0.ɵɵtemplate(1, JoinGridComponent_Conditional_1_Template, 2, 0, "div");
415
- i0.ɵɵelementStart(2, "button", 1);
416
- i0.ɵɵlistener("click", function JoinGridComponent_Template_button_click_2_listener() { return ctx.Save(); });
417
- i0.ɵɵtext(3, "Save");
418
- i0.ɵɵelementEnd();
419
- i0.ɵɵelementStart(4, "button", 1);
420
- i0.ɵɵlistener("click", function JoinGridComponent_Template_button_click_4_listener() { return ctx.CancelEdit(); });
421
- i0.ɵɵtext(5, "Cancel");
422
- i0.ɵɵelementEnd();
423
- i0.ɵɵtemplate(6, JoinGridComponent_Conditional_6_Template, 10, 2, "table", 2);
780
+ i0.ɵɵtemplate(1, JoinGridComponent_Conditional_1_Template, 2, 0, "div")(2, JoinGridComponent_Conditional_2_Template, 2, 1, "button", 1)(3, JoinGridComponent_Conditional_3_Template, 2, 1, "button", 1)(4, JoinGridComponent_Conditional_4_Template, 10, 2, "table", 2);
424
781
  i0.ɵɵelementEnd();
425
782
  } if (rf & 2) {
426
783
  i0.ɵɵadvance();
427
784
  i0.ɵɵconditional(ctx._IsLoading ? 1 : -1);
428
785
  i0.ɵɵadvance();
429
- i0.ɵɵproperty("disabled", ctx.NumDirtyRecords === 0);
430
- i0.ɵɵadvance(2);
431
- i0.ɵɵproperty("disabled", ctx.NumDirtyRecords === 0);
432
- i0.ɵɵadvance(2);
433
- i0.ɵɵconditional(!ctx._IsLoading ? 6 : -1);
434
- } }, dependencies: [i1.NgClass, i1.NgForOf, i2.ButtonComponent, i3.LoaderComponent, i4.FillContainer], styles: [".wrapper[_ngcontent-%COMP%] {\n overflow: auto;\n}\n\n\n\ntable[_ngcontent-%COMP%] {\n margin-left: 5px;\n margin-top: 5px;\n border-collapse: collapse; \n\n}\n\nbutton[_ngcontent-%COMP%] {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n \ntable[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background-color: #f2f2f2; \n\n color: black; \n\n font-weight: bold; \n\n cursor: pointer;\n}\n\n.permission-left-col[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n\n\ntable[_ngcontent-%COMP%] th[_ngcontent-%COMP%], table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n border: 1px solid gray; \n\n height: 36px; \n\n text-align: center;\n padding: 0 8px; \n\n}\n\n\n\ntable[_ngcontent-%COMP%] th[_ngcontent-%COMP%]:first-child, table[_ngcontent-%COMP%] td[_ngcontent-%COMP%]:first-child {\n min-width: 150px; \n\n text-align: left;\n}\n\n\n\ntable[_ngcontent-%COMP%] th[_ngcontent-%COMP%]:not(:first-child), table[_ngcontent-%COMP%] td[_ngcontent-%COMP%]:not(:first-child) {\n width: 100px; \n\n}\n\n\n\ntable[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:nth-child(odd) {\n background-color: white; \n\n}\n\ntable[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:nth-child(even) {\n background-color: #e7f4ff; \n\n}\n\ntable[_ngcontent-%COMP%] tr.dirty-row[_ngcontent-%COMP%] {\n font-style: italic;\n background-color: #ffcccc;\n}\n\ntable[_ngcontent-%COMP%] td.dirty-cell[_ngcontent-%COMP%] {\n font-style: italic;\n background-color: #ffcccc;\n}"] });
786
+ i0.ɵɵconditional(ctx.ShowSaveButton ? 2 : -1);
787
+ i0.ɵɵadvance();
788
+ i0.ɵɵconditional(ctx.ShowCancelButton ? 3 : -1);
789
+ i0.ɵɵadvance();
790
+ i0.ɵɵconditional(!ctx._IsLoading ? 4 : -1);
791
+ } }, dependencies: [i1.NgClass, i1.NgForOf, i2.TextBoxComponent, i2.CheckBoxDirective, i3.ButtonComponent, i4.DropDownListComponent, i5.LoaderComponent, i6.FillContainer], styles: [".wrapper[_ngcontent-%COMP%] {\n overflow: auto;\n}\n\nbutton[_ngcontent-%COMP%] {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n \nbutton.cellButton[_ngcontent-%COMP%] {\n margin-left: 5px;\n margin-top: 5px;\n width: 30px;\n margin-bottom: 5px;\n float: right;\n}\n\ntable[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background-color: #f2f2f2; \n\n color: black; \n\n font-weight: bold; \n\n}\n\n\n\n\n\n\n\n\ntable[_ngcontent-%COMP%] th[_ngcontent-%COMP%], table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n border: 1px solid gray; \n\n height: 36px; \n\n text-align: center;\n padding: 0 8px; \n\n}\n\ntd.column-cell[_ngcontent-%COMP%] {\n margin: 0;\n \n\n \n\n text-align: left;\n}\n\n\n\ntable[_ngcontent-%COMP%] th[_ngcontent-%COMP%]:first-child, table[_ngcontent-%COMP%] td[_ngcontent-%COMP%]:first-child {\n min-width: 150px; \n\n text-align: left;\n vertical-align: middle;\n}\n\n.checkbox-column[_ngcontent-%COMP%] {\n width: 100px; \n\n}\n\n\n\ntable[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:nth-child(odd) {\n background-color: white; \n\n}\n\ntable[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:nth-child(even) {\n background-color: #e7f4ff; \n\n}\n\ntable[_ngcontent-%COMP%] tr.dirty-row[_ngcontent-%COMP%] {\n font-style: italic;\n background-color: #ffcccc;\n}\n\ntable[_ngcontent-%COMP%] td.dirty-cell[_ngcontent-%COMP%] {\n font-style: italic;\n background-color: #ffcccc;\n}"] });
435
792
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(JoinGridComponent, [{
436
793
  type: Component,
437
- args: [{ selector: 'mj-join-grid', template: "<div mjFillContainer class=\"wrapper\"> \n @if (_IsLoading) {\n <div><kendo-loader></kendo-loader></div>\n }\n <button [disabled]=\"NumDirtyRecords === 0\" kendoButton (click)=\"Save()\">Save</button>\n <button [disabled]=\"NumDirtyRecords === 0\" kendoButton (click)=\"CancelEdit()\">Cancel</button>\n @if (!_IsLoading) {\n <table class=\"grid\">\n <thead>\n <tr>\n <!-- First column is the name of the Rows Entity -->\n <th>{{RowsEntityName}}</th>\n @if (ColumnsMode === 'Entity') {\n @for (colRecord of this._columnsEntityData; track colRecord) {\n <th>{{colRecord.Get(this.ColumnsEntityDisplayField)}}</th>\n }\n }\n @else {\n <!-- we need one column for each of the fields in the JoinEntityDisplayColumns array -->\n @for (colName of JoinEntityDisplayColumns; track colName) {\n <th>{{colName}}</th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (row of _GridData; track row) {\n <tr [ngClass]=\"IsRecordReallyDirty(row) ? 'dirty-row' : ''\">\n <td class=\"first-column\">\n <span>{{row.FirstColValue}}</span>\n </td>\n @if (ColumnsMode === 'Fields') {\n <td *ngFor=\"let colName of JoinEntityDisplayColumns\">\n <input type=\"checkbox\" kendoCheckBox>\n </td>\n }\n @else {\n @for (cell of row.ColumnData; track cell) {\n <!-- loop through all the columns and display a checkbox and check it if we have a match in the current row -->\n <td (click)=\"_FlipRecord($event, row, cell)\"\n [ngClass]=\"IsCellReallyDirty(cell) ? 'dirty-cell' : ''\">\n <input type=\"checkbox\" \n kendoCheckBox \n [checked]=\"_IsColumnChecked(cell)\" \n (click)=\"_FlipRecord($event, row, cell, true)\">\n </td>\n }\n }\n </tr> \n } \n </tbody>\n </table>\n }\n</div>", styles: [".wrapper {\n overflow: auto;\n}\n\n/* Style for the whole table */\ntable {\n margin-left: 5px;\n margin-top: 5px;\n border-collapse: collapse; /* Ensures border collapse for a cleaner look */\n}\n\nbutton {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n \ntable th {\n background-color: #f2f2f2; /* Light gray background for headers */\n color: black; /* Black text color for headers */\n font-weight: bold; /* Bold font weight for headers */\n cursor: pointer;\n}\n\n.permission-left-col {\n cursor: pointer;\n}\n\n/* Style for all table cells */\ntable th, table td {\n border: 1px solid gray; /* Gray border for cells */\n height: 36px; /* Fixed height for all rows */\n text-align: center;\n padding: 0 8px; /* Add some padding inside cells */\n}\n\n/* Specific styles for the first column */\ntable th:first-child, table td:first-child {\n min-width: 150px; /* Set width for the first column */\n text-align: left;\n}\n\n/* Specific styles for the \"Can\" columns */\ntable th:not(:first-child), table td:not(:first-child) {\n width: 100px; /* Set width for \"Can\" columns */\n}\n\n/* Alternating row background colors */\ntable tr:nth-child(odd) {\n background-color: white; /* Light color for odd rows */\n}\n\ntable tr:nth-child(even) {\n background-color: #e7f4ff; /* Light blue for even rows */\n}\n\ntable tr.dirty-row {\n font-style: italic;\n background-color: #ffcccc;\n}\n\ntable td.dirty-cell {\n font-style: italic;\n background-color: #ffcccc;\n}"] }]
438
- }], () => [{ type: i0.ChangeDetectorRef }], { RowsEntityName: [{
794
+ args: [{ selector: 'mj-join-grid', template: "<div mjFillContainer class=\"wrapper\"> \n @if (_IsLoading) {\n <div><kendo-loader></kendo-loader></div>\n }\n @if (ShowSaveButton) {\n <button [disabled]=\"NumDirtyRecords === 0\" kendoButton (click)=\"Save()\">Save</button>\n }\n @if (ShowCancelButton) {\n <button [disabled]=\"NumDirtyRecords === 0\" kendoButton (click)=\"CancelEdit()\">Cancel</button>\n }\n @if (!_IsLoading) {\n <table class=\"grid\">\n <thead>\n <tr>\n <!-- First column is the name of the Rows Entity -->\n <th>{{RowsEntityDisplayNameOrName}}</th>\n @if (ColumnsMode === 'Entity') {\n @for (colRecord of this._columnsEntityData; track colRecord) {\n <th class=\"checkbox-column\">{{colRecord.Get(this.ColumnsEntityDisplayField)}}</th>\n }\n }\n @else {\n <!-- we need one column for each of the fields in the JoinEntityDisplayColumns array -->\n @for (colName of JoinEntityDisplayColumns; track colName) {\n <th>{{colName}}</th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @for (row of _GridData; track row) {\n <tr [ngClass]=\"IsRecordReallyDirty(row) ? 'dirty-row' : ''\">\n <td class=\"first-column\">\n <span>{{row.FirstColValue}}</span>\n @if (EditMode !== 'None'){\n @if (!row.JoinExists) {\n <button kendoButton class=\"cellButton\" (click)=\"AddJoinEntityRecord(row)\"><span class=\"fa-solid fa-plus\"></span></button>\n }\n @else {\n <button kendoButton class=\"cellButton\" (click)=\"RemoveJoinEntityRecord(row)\"><span class=\"fa-solid fa-minus\"></span></button>\n } \n }\n </td>\n @if (ColumnsMode === 'Fields') {\n <td class=\"column-cell\" *ngFor=\"let colName of JoinEntityDisplayColumns; let i = index\">\n @if (EditMode !== 'None') {\n @if (row.JoinExists) {\n @if (GetJoinEntityField(colName).ValueListType === \"None\") {\n @if (GetJoinEntityField(colName).TSType === EntityFieldTSType.Boolean) {\n <input type=\"checkbox\" [checked]=\"row.GetColumnValue(i)\" (change)=\"UpdateCellValue(row, i, $event)\" />\n }\n @else {\n <kendo-textbox [value]=\"row.GetColumnValue(i)\" (change)=\"UpdateCellValue(row, i, $event)\" /> \n }\n }\n @else {\n <kendo-dropdownlist\n [data]=\"GetJoinEntityFieldValues(colName)\"\n [value]=\"row.GetColumnValue(i)\"\n (selectionChange)=\"UpdateCellValueDirect(row, i, $event)\"\n >\n </kendo-dropdownlist>\n }\n }\n }\n @else {\n {{row.GetColumnValue(i)}}\n }\n </td>\n }\n @else {\n @for (cell of row.ColumnData; track cell) {\n <!-- loop through all the columns and display a checkbox and check it if we have a match in the current row -->\n <td class=\"checkbox-column\" (click)=\"_FlipRecord($event, row, cell)\"\n [ngClass]=\"IsCellReallyDirty(cell) ? 'dirty-cell' : ''\">\n @if (EditMode !== 'None') {\n <input type=\"checkbox\" \n kendoCheckBox \n [checked]=\"_IsColumnChecked(cell)\" \n (click)=\"_FlipRecord($event, row, cell, true)\">\n }\n @else {\n {{cell.value ? '\u2713' : ''}}\n }\n </td>\n }\n }\n </tr> \n } \n </tbody>\n </table>\n }\n</div>", styles: [".wrapper {\n overflow: auto;\n}\n\nbutton {\n margin-left: 5px;\n margin-top: 5px;\n width: 125px;\n}\n \nbutton.cellButton {\n margin-left: 5px;\n margin-top: 5px;\n width: 30px;\n margin-bottom: 5px;\n float: right;\n}\n\ntable th {\n background-color: #f2f2f2; /* Light gray background for headers */\n color: black; /* Black text color for headers */\n font-weight: bold; /* Bold font weight for headers */\n}\n/* \n.permission-left-col {\n cursor: pointer;\n} */\n\n/* Style for all table cells */\ntable th, table td {\n border: 1px solid gray; /* Gray border for cells */\n height: 36px; /* Fixed height for all rows */\n text-align: center;\n padding: 0 8px; /* Add some padding inside cells */\n}\n\ntd.column-cell {\n margin: 0;\n /* display: flex; */\n /* align-items: center; */\n text-align: left;\n}\n\n/* Specific styles for the first column */\ntable th:first-child, table td:first-child {\n min-width: 150px; /* Set width for the first column */\n text-align: left;\n vertical-align: middle;\n}\n\n.checkbox-column {\n width: 100px; /* Set width for \"Can\" columns */\n}\n\n/* Alternating row background colors */\ntable tr:nth-child(odd) {\n background-color: white; /* Light color for odd rows */\n}\n\ntable tr:nth-child(even) {\n background-color: #e7f4ff; /* Light blue for even rows */\n}\n\ntable tr.dirty-row {\n font-style: italic;\n background-color: #ffcccc;\n}\n\ntable td.dirty-cell {\n font-style: italic;\n background-color: #ffcccc;\n}"] }]
795
+ }], () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], { RowsEntityName: [{
796
+ type: Input
797
+ }], RowsEntityDisplayName: [{
439
798
  type: Input
440
799
  }], RowsEntityDisplayField: [{
441
800
  type: Input
@@ -473,11 +832,19 @@ JoinGridComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: JoinGridC
473
832
  type: Input
474
833
  }], JoinEntityDisplayColumns: [{
475
834
  type: Input
835
+ }], JoinEntityExtraFilter: [{
836
+ type: Input
476
837
  }], CheckBoxValueMode: [{
477
838
  type: Input
478
839
  }], CheckBoxValueField: [{
479
840
  type: Input
480
841
  }], NewRecordDefaultValues: [{
481
842
  type: Input
843
+ }], ShowSaveButton: [{
844
+ type: Input
845
+ }], ShowCancelButton: [{
846
+ type: Input
847
+ }], EditMode: [{
848
+ type: Input
482
849
  }] }); })();
483
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(JoinGridComponent, { className: "JoinGridComponent", filePath: "src/lib/join-grid/join-grid.component.ts", lineNumber: 24 }); })();
850
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(JoinGridComponent, { className: "JoinGridComponent", filePath: "src/lib/join-grid/join-grid.component.ts", lineNumber: 42 }); })();
@@ -4,12 +4,13 @@ import * as i2 from "@angular/common";
4
4
  import * as i3 from "@angular/forms";
5
5
  import * as i4 from "@progress/kendo-angular-dialog";
6
6
  import * as i5 from "@progress/kendo-angular-grid";
7
- import * as i6 from "@progress/kendo-angular-buttons";
8
- import * as i7 from "@progress/kendo-angular-dropdowns";
9
- import * as i8 from "@progress/kendo-angular-indicators";
10
- import * as i9 from "@memberjunction/ng-container-directives";
7
+ import * as i6 from "@progress/kendo-angular-inputs";
8
+ import * as i7 from "@progress/kendo-angular-buttons";
9
+ import * as i8 from "@progress/kendo-angular-dropdowns";
10
+ import * as i9 from "@progress/kendo-angular-indicators";
11
+ import * as i10 from "@memberjunction/ng-container-directives";
11
12
  export declare class JoinGridModule {
12
13
  static ɵfac: i0.ɵɵFactoryDeclaration<JoinGridModule, never>;
13
- static ɵmod: i0.ɵɵNgModuleDeclaration<JoinGridModule, [typeof i1.JoinGridComponent], [typeof i2.CommonModule, typeof i3.FormsModule, typeof i4.DialogsModule, typeof i5.GridModule, typeof i6.ButtonsModule, typeof i7.DropDownsModule, typeof i4.DialogsModule, typeof i8.IndicatorsModule, typeof i9.ContainerDirectivesModule], [typeof i1.JoinGridComponent]>;
14
+ static ɵmod: i0.ɵɵNgModuleDeclaration<JoinGridModule, [typeof i1.JoinGridComponent], [typeof i2.CommonModule, typeof i3.FormsModule, typeof i4.DialogsModule, typeof i5.GridModule, typeof i6.InputsModule, typeof i7.ButtonsModule, typeof i8.DropDownsModule, typeof i4.DialogsModule, typeof i9.IndicatorsModule, typeof i10.ContainerDirectivesModule], [typeof i1.JoinGridComponent]>;
14
15
  static ɵinj: i0.ɵɵInjectorDeclaration<JoinGridModule>;
15
16
  }
@@ -6,6 +6,7 @@ import { DialogsModule } from "@progress/kendo-angular-dialog";
6
6
  import { ButtonsModule } from '@progress/kendo-angular-buttons';
7
7
  import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
8
8
  import { IndicatorsModule } from '@progress/kendo-angular-indicators';
9
+ import { InputsModule } from '@progress/kendo-angular-inputs';
9
10
  // LOCAL
10
11
  import { JoinGridComponent } from './join-grid/join-grid.component';
11
12
  import { GridModule } from '@progress/kendo-angular-grid';
@@ -19,6 +20,7 @@ JoinGridModule.ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ imports: [CommonMod
19
20
  FormsModule,
20
21
  DialogsModule,
21
22
  GridModule,
23
+ InputsModule,
22
24
  ButtonsModule,
23
25
  DropDownsModule,
24
26
  DialogsModule,
@@ -35,6 +37,7 @@ JoinGridModule.ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ imports: [CommonMod
35
37
  FormsModule,
36
38
  DialogsModule,
37
39
  GridModule,
40
+ InputsModule,
38
41
  ButtonsModule,
39
42
  DropDownsModule,
40
43
  DialogsModule,
@@ -50,6 +53,7 @@ JoinGridModule.ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ imports: [CommonMod
50
53
  FormsModule,
51
54
  DialogsModule,
52
55
  GridModule,
56
+ InputsModule,
53
57
  ButtonsModule,
54
58
  DropDownsModule,
55
59
  DialogsModule,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-join-grid",
3
- "version": "1.7.1",
3
+ "version": "1.8.0",
4
4
  "description": "MemberJunction: Grid component that is able to display/edit the relationship between two entities. For example being able to edit Users + Roles in a single grid.",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -25,15 +25,17 @@
25
25
  "@angular/router": "18.0.2"
26
26
  },
27
27
  "dependencies": {
28
- "@memberjunction/core-entities": "1.7.1",
29
- "@memberjunction/global": "1.7.1",
30
- "@memberjunction/core": "1.7.1",
31
- "@memberjunction/ng-shared": "1.7.1",
32
- "@memberjunction/ng-container-directives": "1.7.1",
28
+ "@memberjunction/core-entities": "1.8.0",
29
+ "@memberjunction/global": "1.8.0",
30
+ "@memberjunction/core": "1.8.0",
31
+ "@memberjunction/ng-base-types": "1.8.0",
32
+ "@memberjunction/ng-container-directives": "1.8.0",
33
+ "@memberjunction/ng-shared": "1.8.0",
33
34
  "@progress/kendo-angular-buttons": "16.2.0",
34
35
  "@progress/kendo-angular-dialog": "16.2.0",
35
36
  "@progress/kendo-angular-layout": "16.2.0",
36
37
  "@progress/kendo-angular-grid": "16.2.0",
38
+ "@progress/kendo-angular-inputs": "16.2.0",
37
39
  "@progress/kendo-angular-indicators": "16.2.0",
38
40
  "tslib": "^2.3.0"
39
41
  },