@memberjunction/ng-base-forms 1.8.0 → 2.0.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.
- package/dist/lib/base-field-component.d.ts +5 -1
- package/dist/lib/base-field-component.d.ts.map +1 -1
- package/dist/lib/base-field-component.js +11 -5
- package/dist/lib/link-field.component.d.ts +17 -3
- package/dist/lib/link-field.component.d.ts.map +1 -1
- package/dist/lib/link-field.component.js +210 -68
- package/dist/lib/section-loader-component.js +1 -1
- package/package.json +11 -11
|
@@ -33,6 +33,10 @@ export declare class MJFormField extends BaseRecordComponent implements AfterVie
|
|
|
33
33
|
* valid when the FieldName field is a foreign key field to another entity.
|
|
34
34
|
*/
|
|
35
35
|
LinkType: 'Email' | 'URL' | 'Record' | 'None';
|
|
36
|
+
/**
|
|
37
|
+
* Optional, when the field type is a linked field, you can specify if a search box is shown or a dropdown component is shown. The default is 'search'.
|
|
38
|
+
*/
|
|
39
|
+
LinkComponentType: 'Search' | 'Dropdown';
|
|
36
40
|
/**
|
|
37
41
|
* If set to false, the label for the field will not be shown. The default is true.
|
|
38
42
|
*/
|
|
@@ -65,6 +69,6 @@ export declare class MJFormField extends BaseRecordComponent implements AfterVie
|
|
|
65
69
|
constructor(renderer: Renderer2, cdr: ChangeDetectorRef);
|
|
66
70
|
ngAfterViewInit(): void;
|
|
67
71
|
static ɵfac: i0.ɵɵFactoryDeclaration<MJFormField, never>;
|
|
68
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<MJFormField, "mj-form-field", never, { "record": { "alias": "record"; "required": false; }; "EditMode": { "alias": "EditMode"; "required": false; }; "FieldName": { "alias": "FieldName"; "required": false; }; "Type": { "alias": "Type"; "required": false; }; "LinkType": { "alias": "LinkType"; "required": false; }; "ShowLabel": { "alias": "ShowLabel"; "required": false; }; "DisplayName": { "alias": "DisplayName"; "required": false; }; "PossibleValues": { "alias": "PossibleValues"; "required": false; }; "Value": { "alias": "Value"; "required": false; }; }, { "ValueChange": "ValueChange"; }, never, never, false, never>;
|
|
72
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MJFormField, "mj-form-field", never, { "record": { "alias": "record"; "required": false; }; "EditMode": { "alias": "EditMode"; "required": false; }; "FieldName": { "alias": "FieldName"; "required": false; }; "Type": { "alias": "Type"; "required": false; }; "LinkType": { "alias": "LinkType"; "required": false; }; "LinkComponentType": { "alias": "LinkComponentType"; "required": false; }; "ShowLabel": { "alias": "ShowLabel"; "required": false; }; "DisplayName": { "alias": "DisplayName"; "required": false; }; "PossibleValues": { "alias": "PossibleValues"; "required": false; }; "Value": { "alias": "Value"; "required": false; }; }, { "ValueChange": "ValueChange"; }, never, never, false, never>;
|
|
69
73
|
}
|
|
70
74
|
//# sourceMappingURL=base-field-component.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-field-component.d.ts","sourceRoot":"","sources":["../../src/lib/base-field-component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAyB,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3I,OAAO,EAAE,UAAU,EAAE,eAAe,EAAqB,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;;AAGjD;;;;;GAKG;AACH,qBAKa,WAAY,SAAQ,mBAAoB,YAAW,aAAa;
|
|
1
|
+
{"version":3,"file":"base-field-component.d.ts","sourceRoot":"","sources":["../../src/lib/base-field-component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAyB,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3I,OAAO,EAAE,UAAU,EAAE,eAAe,EAAqB,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;;AAGjD;;;;;GAKG;AACH,qBAKa,WAAY,SAAQ,mBAAoB,YAAW,aAAa;IAmHzE,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,GAAG;IAnHb;;OAEG;IACM,MAAM,EAAG,UAAU,CAAC;IAC7B;;OAEG;IACM,QAAQ,EAAE,OAAO,CAAS;IACnC;;OAEG;IACM,SAAS,EAAE,MAAM,CAAM;IAChC;;OAEG;IACM,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,gBAAgB,GAAG,YAAY,GAAG,UAAU,GAAG,cAAc,GAAG,UAAU,GAAG,MAAM,CAAa;IACxI;;;OAGG;IACM,QAAQ,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAU;IAEhE;;OAEG;IACM,iBAAiB,EAAE,QAAQ,GAAG,UAAU,CAAc;IAE/D;;OAEG;IACM,SAAS,EAAE,OAAO,CAAQ;IAEnC,SAAS,uDAAa;IAEtB,OAAO,CAAC,YAAY,CAAuB;IAC3C;;OAEG;IACH,IACW,WAAW,IAAI,MAAM,CAO/B;IAED,IAAW,WAAW,CAAC,QAAQ,EAAE,MAAM,EAEtC;IAED,IAAW,YAAY,IAAI,MAAM,CAEhC;IAED,OAAO,CAAC,eAAe,CAAyB;IAChD;;;OAGG;IACH,IAAa,cAAc,IAAI,MAAM,EAAE,CAOtC;IAED,IAAI,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,EAEpC;IAED,IACW,KAAK,IAAI,GAAG,CAUtB;IACD,IAAW,KAAK,CAAC,QAAQ,EAAE,GAAG,EAM7B;IACS,WAAW,oBAA2B;IAEhD;;OAEG;IACH,IAAW,eAAe,IAAI,OAAO,CAIpC;IAED,IAAW,SAAS,IAAI,eAAe,CAItC;IAEyC,QAAQ,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAClF,OAAO,CAAC,QAAQ,CAA+B;gBAGrC,QAAQ,EAAE,SAAS,EACnB,GAAG,EAAE,iBAAiB;IAKhC,eAAe,IAAI,IAAI;yCAzHZ,WAAW;2CAAX,WAAW;CAgMvB"}
|
|
@@ -105,7 +105,7 @@ function MJFormField_Conditional_0_div_1_Conditional_2_Template(rf, ctx) { if (r
|
|
|
105
105
|
i0.ɵɵelement(0, "mj-link-field", 9);
|
|
106
106
|
} if (rf & 2) {
|
|
107
107
|
const ctx_r0 = i0.ɵɵnextContext(3);
|
|
108
|
-
i0.ɵɵproperty("record", ctx_r0.record)("FieldName", ctx_r0.FieldName);
|
|
108
|
+
i0.ɵɵproperty("record", ctx_r0.record)("FieldName", ctx_r0.FieldName)("LinkComponentType", ctx_r0.LinkComponentType);
|
|
109
109
|
} }
|
|
110
110
|
function MJFormField_Conditional_0_div_1_Conditional_3_Case_0_Template(rf, ctx) { if (rf & 1) {
|
|
111
111
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
@@ -192,7 +192,7 @@ function MJFormField_Conditional_0_div_1_Conditional_3_Template(rf, ctx) { if (r
|
|
|
192
192
|
} }
|
|
193
193
|
function MJFormField_Conditional_0_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
194
194
|
i0.ɵɵelementStart(0, "div", 2);
|
|
195
|
-
i0.ɵɵtemplate(1, MJFormField_Conditional_0_div_1_Conditional_1_Template, 2, 1, "label")(2, MJFormField_Conditional_0_div_1_Conditional_2_Template, 1,
|
|
195
|
+
i0.ɵɵtemplate(1, MJFormField_Conditional_0_div_1_Conditional_1_Template, 2, 1, "label")(2, MJFormField_Conditional_0_div_1_Conditional_2_Template, 1, 3, "mj-link-field", 9)(3, MJFormField_Conditional_0_div_1_Conditional_3_Template, 8, 1);
|
|
196
196
|
i0.ɵɵelementEnd();
|
|
197
197
|
} if (rf & 2) {
|
|
198
198
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
@@ -313,6 +313,10 @@ export class MJFormField extends BaseRecordComponent {
|
|
|
313
313
|
* valid when the FieldName field is a foreign key field to another entity.
|
|
314
314
|
*/
|
|
315
315
|
this.LinkType = 'None';
|
|
316
|
+
/**
|
|
317
|
+
* Optional, when the field type is a linked field, you can specify if a search box is shown or a dropdown component is shown. The default is 'search'.
|
|
318
|
+
*/
|
|
319
|
+
this.LinkComponentType = 'Dropdown';
|
|
316
320
|
/**
|
|
317
321
|
* If set to false, the label for the field will not be shown. The default is true.
|
|
318
322
|
*/
|
|
@@ -353,14 +357,14 @@ MJFormField.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJFormField, se
|
|
|
353
357
|
} if (rf & 2) {
|
|
354
358
|
let _t;
|
|
355
359
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.markdown = _t.first);
|
|
356
|
-
} }, inputs: { record: "record", EditMode: "EditMode", FieldName: "FieldName", Type: "Type", LinkType: "LinkType", ShowLabel: "ShowLabel", DisplayName: "DisplayName", PossibleValues: "PossibleValues", Value: "Value" }, outputs: { ValueChange: "ValueChange" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [["markdown", ""], ["class", "record-form-row", 4, "ngIf"], [1, "record-form-row"], [4, "ngIf"], ["mjEmailLink", "", 3, "field"], ["mjWebLink", "", 3, "field"], ["mjFieldLink", "", 3, "record", "fieldName"], [3, "value", "readonly", "languages", "language"], [3, "data"], [3, "record", "FieldName"], [3, "ngModel", "languages", "language"], [3, "ngModel"], ["mjFillContainer", "", 3, "ngModel", "fillWidth", "fillHeight"], [3, "value"], ["type", "checkbox", "kendoCheckBox", "", 3, "ngModel"], [3, "data", "ngModel"], [3, "data", "allowCustom", "ngModel"], [3, "ngModelChange", "ngModel", "languages", "language"], [3, "ngModelChange", "ngModel"], ["mjFillContainer", "", 3, "ngModelChange", "ngModel", "fillWidth", "fillHeight"], [3, "valueChange", "value"], ["type", "checkbox", "kendoCheckBox", "", 3, "ngModelChange", "ngModel"], [3, "ngModelChange", "data", "ngModel"], [3, "ngModelChange", "data", "allowCustom", "ngModel"]], template: function MJFormField_Template(rf, ctx) { if (rf & 1) {
|
|
360
|
+
} }, inputs: { record: "record", EditMode: "EditMode", FieldName: "FieldName", Type: "Type", LinkType: "LinkType", LinkComponentType: "LinkComponentType", ShowLabel: "ShowLabel", DisplayName: "DisplayName", PossibleValues: "PossibleValues", Value: "Value" }, outputs: { ValueChange: "ValueChange" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [["markdown", ""], ["class", "record-form-row", 4, "ngIf"], [1, "record-form-row"], [4, "ngIf"], ["mjEmailLink", "", 3, "field"], ["mjWebLink", "", 3, "field"], ["mjFieldLink", "", 3, "record", "fieldName"], [3, "value", "readonly", "languages", "language"], [3, "data"], [3, "record", "FieldName", "LinkComponentType"], [3, "ngModel", "languages", "language"], [3, "ngModel"], ["mjFillContainer", "", 3, "ngModel", "fillWidth", "fillHeight"], [3, "value"], ["type", "checkbox", "kendoCheckBox", "", 3, "ngModel"], [3, "data", "ngModel"], [3, "data", "allowCustom", "ngModel"], [3, "ngModelChange", "ngModel", "languages", "language"], [3, "ngModelChange", "ngModel"], ["mjFillContainer", "", 3, "ngModelChange", "ngModel", "fillWidth", "fillHeight"], [3, "valueChange", "value"], ["type", "checkbox", "kendoCheckBox", "", 3, "ngModelChange", "ngModel"], [3, "ngModelChange", "data", "ngModel"], [3, "ngModelChange", "data", "allowCustom", "ngModel"]], template: function MJFormField_Template(rf, ctx) { if (rf & 1) {
|
|
357
361
|
i0.ɵɵtemplate(0, MJFormField_Conditional_0_Template, 2, 2);
|
|
358
362
|
} if (rf & 2) {
|
|
359
363
|
i0.ɵɵconditional(ctx.record.IsSaved || !ctx.IsFieldReadOnly ? 0 : -1);
|
|
360
364
|
} }, dependencies: [i1.NgIf, i2.CheckboxControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.TextAreaComponent, i3.TextBoxComponent, i3.NumericTextBoxComponent, i3.CheckBoxDirective, i4.DatePickerComponent, i5.ComboBoxComponent, i5.DropDownListComponent, i6.EmailLink, i6.FieldLink, i6.WebLink, i7.FillContainer, i8.CodeEditorComponent, i9.MarkdownComponent, i10.MJLinkField], styles: [".record-form-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: auto 1fr;\n align-items: start;\n gap: 10px;\n margin-bottom: 12px;\n padding-top: 5px;\n padding-bottom: 5px;\n align-items: start; \n\n} \n \n \n.record-form-row[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-weight: bold;\n padding-right: 10px;\n width: 240px;\n margin-bottom: 0;\n align-self: start; \n\n}\n\n\n\n\n\n.record-form-row[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > p[_ngcontent-%COMP%], \n.record-form-row[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > h1[_ngcontent-%COMP%], \n.record-form-row[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > h2[_ngcontent-%COMP%], \n.record-form-row[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > h3[_ngcontent-%COMP%], \n.record-form-row[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > h4[_ngcontent-%COMP%], \n.record-form-row[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > h5[_ngcontent-%COMP%], \n.record-form-row[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > h6[_ngcontent-%COMP%] {\n margin:0 !important;\n}\n\nmarkdown[_ngcontent-%COMP%] {\n font-size: 1rem; \n\n}\n\n\n@media (min-width: 768px) {\n .record-form-row[_ngcontent-%COMP%] {\n display: grid; \n\n grid-template-columns: auto 1fr;\n align-items: start; \n\n gap: 10px;\n margin-bottom: 12px;\n padding-top: 5px;\n padding-bottom: 5px;\n }\n\n .record-form-row[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n width: 240px;\n margin-bottom: 0;\n align-self: start; \n\n }\n}"] });
|
|
361
365
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJFormField, [{
|
|
362
366
|
type: Component,
|
|
363
|
-
args: [{ selector: 'mj-form-field', template: "<!--\n Using a blend of *ngIf and the new @switch control flow because of a bug in early Angular 17 where\n the @if wrapping the @switch didn't fully remove elements when swtiching back and forth. In the future if Angular fixes the bug\n we can get rid of the *ngIf outer div blocks and instead use @if and contain the @switch within the same div block.\n-->\n@if (record.IsSaved || !IsFieldReadOnly) {\n <!-- We only render a field if the record is either saved, or the field is editable. Meaning, for NEW records, we only show editable fields -->\n <div class=\"record-form-row\" *ngIf=\"!EditMode || IsFieldReadOnly\">\n <label *ngIf=\"ShowLabel\">{{DisplayName}}</label>\n @switch (LinkType) {\n @case ('None') {\n @if (ExtendedType === 'Code') {\n <mj-code-editor [value]=\"record.Get(FieldName)\" [readonly]=\"true\" [languages]=\"languages\" [language]=\"'JavaScript'\"></mj-code-editor>\n }\n @else if (FieldInfo.Length === -1) {\n <!-- this is a varchar(max) type of field -->\n <markdown #markdown [data]=\"record.Get(FieldName)\"></markdown>\n <!-- <span [innerHTML]=\"record.Get(FieldName) | formatText\"></span> -->\n }\n @else {\n <span>{{FormatValue(FieldName, 0)}}</span>\n }\n }\n @case ('Email') {\n <span mjEmailLink [field]=\"record.GetFieldByName(FieldName)\" >{{FormatValue(FieldName, 0)}}</span>\n }\n @case ('URL') {\n <span mjWebLink [field]=\"record.GetFieldByName(FieldName)\" >{{FormatValue(FieldName, 0)}}</span>\n }\n @case ('Record') {\n <span mjFieldLink [record]=\"record\" [fieldName]=\"FieldName\" >{{FormatValue(FieldName, 0)}}</span>\n }\n }\n </div>\n <div class=\"record-form-row\" *ngIf=\"EditMode && !IsFieldReadOnly\">\n @if (ShowLabel) {\n <label>{{DisplayName}}</label>\n }\n @if (FieldInfo && FieldInfo.RelatedEntity && FieldInfo.RelatedEntity.length > 0) {\n <!-- Foreign Key Link here -->\n <mj-link-field [record]=\"record\" [FieldName]=\"FieldName\"></mj-link-field>\n }\n @else {\n <!-- Not a foreign key -->\n @switch (Type) {\n @case ('code') {\n <mj-code-editor [(ngModel)]=\"Value\" [languages]=\"languages\" [language]=\"'JavaScript'\"></mj-code-editor>\n }\n @case ('textbox') {\n <kendo-textbox [(ngModel)]=\"Value\" />\n }\n @case ('textarea') {\n <kendo-textarea [(ngModel)]=\"Value\" mjFillContainer [fillWidth]=\"ShowLabel ? false : true\" [fillHeight]=\"ShowLabel ? false : true\" ></kendo-textarea>\n }\n @case ('numerictextbox') {\n <kendo-numerictextbox [(value)]=\"Value\" />\n }\n @case ('datepicker') {\n <kendo-datepicker [(value)]=\"Value\"></kendo-datepicker>\n }\n @case ('checkbox') {\n <input type=\"checkbox\" [(ngModel)]=\"Value\" kendoCheckBox />\n }\n @case ('dropdownlist') {\n <kendo-dropdownlist [data]=\"PossibleValues\" [(ngModel)]=\"Value\"></kendo-dropdownlist>\n }\n @case ('combobox') {\n <kendo-combobox [data]=\"PossibleValues\" [allowCustom]=\"true\" [(ngModel)]=\"Value\"></kendo-combobox>\n }\n }\n }\n </div>\n}\n", styles: [".record-form-row {\n display: grid;\n grid-template-columns: auto 1fr;\n align-items: start;\n gap: 10px;\n margin-bottom: 12px;\n padding-top: 5px;\n padding-bottom: 5px;\n align-items: start; /* Ensure items are aligned at the top */\n} \n \n \n.record-form-row label {\n font-weight: bold;\n padding-right: 10px;\n width: 240px;\n margin-bottom: 0;\n align-self: start; /* Align the label to the start (top) */\n}\n\n/*\n Eliminate the default margin and padding for the markdown elements\n */\n.record-form-row markdown > p,\n.record-form-row markdown > h1,\n.record-form-row markdown > h2,\n.record-form-row markdown > h3,\n.record-form-row markdown > h4,\n.record-form-row markdown > h5,\n.record-form-row markdown > h6 {\n margin:0 !important;\n}\n\nmarkdown {\n font-size: 1rem; /* Adjust this value to match your app's regular text size */\n}\n\n\n@media (min-width: 768px) {\n .record-form-row {\n display: grid; /* Ensure grid display is used for larger screens as well */\n grid-template-columns: auto 1fr;\n align-items: start; /* Keep the alignment at the top */\n gap: 10px;\n margin-bottom: 12px;\n padding-top: 5px;\n padding-bottom: 5px;\n }\n\n .record-form-row label {\n width: 240px;\n margin-bottom: 0;\n align-self: start; /* Ensure the label is aligned to the top */\n }\n}\n "] }]
|
|
367
|
+
args: [{ selector: 'mj-form-field', template: "<!--\n Using a blend of *ngIf and the new @switch control flow because of a bug in early Angular 17 where\n the @if wrapping the @switch didn't fully remove elements when swtiching back and forth. In the future if Angular fixes the bug\n we can get rid of the *ngIf outer div blocks and instead use @if and contain the @switch within the same div block.\n-->\n@if (record.IsSaved || !IsFieldReadOnly) {\n <!-- We only render a field if the record is either saved, or the field is editable. Meaning, for NEW records, we only show editable fields -->\n <div class=\"record-form-row\" *ngIf=\"!EditMode || IsFieldReadOnly\">\n <label *ngIf=\"ShowLabel\">{{DisplayName}}</label>\n @switch (LinkType) {\n @case ('None') {\n @if (ExtendedType === 'Code') {\n <mj-code-editor [value]=\"record.Get(FieldName)\" [readonly]=\"true\" [languages]=\"languages\" [language]=\"'JavaScript'\"></mj-code-editor>\n }\n @else if (FieldInfo.Length === -1) {\n <!-- this is a varchar(max) type of field -->\n <markdown #markdown [data]=\"record.Get(FieldName)\"></markdown>\n <!-- <span [innerHTML]=\"record.Get(FieldName) | formatText\"></span> -->\n }\n @else {\n <span>{{FormatValue(FieldName, 0)}}</span>\n }\n }\n @case ('Email') {\n <span mjEmailLink [field]=\"record.GetFieldByName(FieldName)\" >{{FormatValue(FieldName, 0)}}</span>\n }\n @case ('URL') {\n <span mjWebLink [field]=\"record.GetFieldByName(FieldName)\" >{{FormatValue(FieldName, 0)}}</span>\n }\n @case ('Record') {\n <span mjFieldLink [record]=\"record\" [fieldName]=\"FieldName\" >{{FormatValue(FieldName, 0)}}</span>\n }\n }\n </div>\n <div class=\"record-form-row\" *ngIf=\"EditMode && !IsFieldReadOnly\">\n @if (ShowLabel) {\n <label>{{DisplayName}}</label>\n }\n @if (FieldInfo && FieldInfo.RelatedEntity && FieldInfo.RelatedEntity.length > 0) {\n <!-- Foreign Key Link here -->\n <mj-link-field [record]=\"record\" [FieldName]=\"FieldName\" [LinkComponentType]=\"LinkComponentType\"></mj-link-field>\n }\n @else {\n <!-- Not a foreign key -->\n @switch (Type) {\n @case ('code') {\n <mj-code-editor [(ngModel)]=\"Value\" [languages]=\"languages\" [language]=\"'JavaScript'\"></mj-code-editor>\n }\n @case ('textbox') {\n <kendo-textbox [(ngModel)]=\"Value\" />\n }\n @case ('textarea') {\n <kendo-textarea [(ngModel)]=\"Value\" mjFillContainer [fillWidth]=\"ShowLabel ? false : true\" [fillHeight]=\"ShowLabel ? false : true\" ></kendo-textarea>\n }\n @case ('numerictextbox') {\n <kendo-numerictextbox [(value)]=\"Value\" />\n }\n @case ('datepicker') {\n <kendo-datepicker [(value)]=\"Value\"></kendo-datepicker>\n }\n @case ('checkbox') {\n <input type=\"checkbox\" [(ngModel)]=\"Value\" kendoCheckBox />\n }\n @case ('dropdownlist') {\n <kendo-dropdownlist [data]=\"PossibleValues\" [(ngModel)]=\"Value\"></kendo-dropdownlist>\n }\n @case ('combobox') {\n <kendo-combobox [data]=\"PossibleValues\" [allowCustom]=\"true\" [(ngModel)]=\"Value\"></kendo-combobox>\n }\n }\n }\n </div>\n}\n", styles: [".record-form-row {\n display: grid;\n grid-template-columns: auto 1fr;\n align-items: start;\n gap: 10px;\n margin-bottom: 12px;\n padding-top: 5px;\n padding-bottom: 5px;\n align-items: start; /* Ensure items are aligned at the top */\n} \n \n \n.record-form-row label {\n font-weight: bold;\n padding-right: 10px;\n width: 240px;\n margin-bottom: 0;\n align-self: start; /* Align the label to the start (top) */\n}\n\n/*\n Eliminate the default margin and padding for the markdown elements\n */\n.record-form-row markdown > p,\n.record-form-row markdown > h1,\n.record-form-row markdown > h2,\n.record-form-row markdown > h3,\n.record-form-row markdown > h4,\n.record-form-row markdown > h5,\n.record-form-row markdown > h6 {\n margin:0 !important;\n}\n\nmarkdown {\n font-size: 1rem; /* Adjust this value to match your app's regular text size */\n}\n\n\n@media (min-width: 768px) {\n .record-form-row {\n display: grid; /* Ensure grid display is used for larger screens as well */\n grid-template-columns: auto 1fr;\n align-items: start; /* Keep the alignment at the top */\n gap: 10px;\n margin-bottom: 12px;\n padding-top: 5px;\n padding-bottom: 5px;\n }\n\n .record-form-row label {\n width: 240px;\n margin-bottom: 0;\n align-self: start; /* Ensure the label is aligned to the top */\n }\n}\n "] }]
|
|
364
368
|
}], () => [{ type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }], { record: [{
|
|
365
369
|
type: Input
|
|
366
370
|
}], EditMode: [{
|
|
@@ -371,6 +375,8 @@ MJFormField.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJFormField, se
|
|
|
371
375
|
type: Input
|
|
372
376
|
}], LinkType: [{
|
|
373
377
|
type: Input
|
|
378
|
+
}], LinkComponentType: [{
|
|
379
|
+
type: Input
|
|
374
380
|
}], ShowLabel: [{
|
|
375
381
|
type: Input
|
|
376
382
|
}], DisplayName: [{
|
|
@@ -385,4 +391,4 @@ MJFormField.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJFormField, se
|
|
|
385
391
|
type: ViewChild,
|
|
386
392
|
args: ['markdown', { static: false }]
|
|
387
393
|
}] }); })();
|
|
388
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJFormField, { className: "MJFormField"
|
|
394
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJFormField, { className: "MJFormField" }); })();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AfterViewInit, ElementRef } from "@angular/core";
|
|
1
|
+
import { AfterViewInit, ElementRef, ChangeDetectorRef } from "@angular/core";
|
|
2
2
|
import { BaseRecordComponent } from "./base-record-component";
|
|
3
3
|
import { BaseEntity, EntityFieldInfo, EntityInfo } from "@memberjunction/core";
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
@@ -9,6 +9,8 @@ import * as i0 from "@angular/core";
|
|
|
9
9
|
* components for field rendering/editing when needed.
|
|
10
10
|
*/
|
|
11
11
|
export declare class MJLinkField extends BaseRecordComponent implements AfterViewInit {
|
|
12
|
+
private cdr;
|
|
13
|
+
constructor(cdr: ChangeDetectorRef);
|
|
12
14
|
/**
|
|
13
15
|
* The record object that contains the field to be rendered. This object should be an instance of BaseEntity or a derived class.
|
|
14
16
|
*/
|
|
@@ -21,11 +23,21 @@ export declare class MJLinkField extends BaseRecordComponent implements AfterVie
|
|
|
21
23
|
* For users of this component, if you already know the name of the record we are linking to, provide it here to reduce DB overhead
|
|
22
24
|
*/
|
|
23
25
|
RecordName?: string;
|
|
26
|
+
/**
|
|
27
|
+
* The type of component to show, search is a user input field that searches for records, dropdown is a dropdown list of records. The default is 'search'. If the related entity has
|
|
28
|
+
* a small list of possible records, it is often desirable to show a dropdown list instead of a search box.
|
|
29
|
+
*/
|
|
30
|
+
LinkComponentType?: 'Search' | 'Dropdown';
|
|
24
31
|
RelatedEntityInfo: EntityInfo | undefined;
|
|
32
|
+
private _SelectedRecord;
|
|
33
|
+
get SelectedRecord(): BaseEntity | undefined;
|
|
34
|
+
set SelectedRecord(val: BaseEntity | undefined);
|
|
25
35
|
RecordLinked: boolean;
|
|
26
|
-
|
|
36
|
+
RelatedEntityRecords: BaseEntity[];
|
|
27
37
|
showMatchingRecords: boolean;
|
|
38
|
+
dropDownColumns: EntityFieldInfo[];
|
|
28
39
|
inputBox: ElementRef;
|
|
40
|
+
private initComponent;
|
|
29
41
|
ngAfterViewInit(): Promise<void>;
|
|
30
42
|
protected AttemptToLinkValue(): Promise<void>;
|
|
31
43
|
get Value(): any;
|
|
@@ -35,8 +47,10 @@ export declare class MJLinkField extends BaseRecordComponent implements AfterVie
|
|
|
35
47
|
onClearClicked(): void;
|
|
36
48
|
RelatedEntityNameField: string;
|
|
37
49
|
protected fetchMatchingRecords(query: string): Promise<void>;
|
|
50
|
+
protected populateDropdownList(): Promise<void>;
|
|
51
|
+
protected SetDropdownValue(): Promise<void>;
|
|
38
52
|
onRecordSelected(linkedRecord: BaseEntity): void;
|
|
39
53
|
static ɵfac: i0.ɵɵFactoryDeclaration<MJLinkField, never>;
|
|
40
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<MJLinkField, "mj-link-field", never, { "record": { "alias": "record"; "required": false; }; "FieldName": { "alias": "FieldName"; "required": false; }; "RecordName": { "alias": "RecordName"; "required": false; }; }, {}, never, never, false, never>;
|
|
54
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MJLinkField, "mj-link-field", never, { "record": { "alias": "record"; "required": false; }; "FieldName": { "alias": "FieldName"; "required": false; }; "RecordName": { "alias": "RecordName"; "required": false; }; "LinkComponentType": { "alias": "LinkComponentType"; "required": false; }; }, {}, never, never, false, never>;
|
|
41
55
|
}
|
|
42
56
|
//# sourceMappingURL=link-field.component.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-field.component.d.ts","sourceRoot":"","sources":["../../src/lib/link-field.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAa,UAAU,EAAoB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"link-field.component.d.ts","sourceRoot":"","sources":["../../src/lib/link-field.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAa,UAAU,EAAoB,iBAAiB,EAA4B,MAAM,eAAe,CAAC;AACpI,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAgB,eAAe,EAAE,UAAU,EAAqB,MAAM,sBAAsB,CAAC;;AAGhH;;;;;GAKG;AACH,qBAKa,WAAY,SAAQ,mBAAoB,YAAW,aAAa;IAC7D,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,iBAAiB;IAG1C;;OAEG;IACM,MAAM,EAAG,UAAU,CAAC;IAE7B;;OAEG;IACM,SAAS,EAAE,MAAM,CAAM;IAEhC;;OAEG;IACM,UAAU,CAAC,EAAE,MAAM,CAAM;IAElC;;;OAGG;IACM,iBAAiB,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAY;IAEvD,iBAAiB,EAAE,UAAU,GAAG,SAAS,CAAa;IAE7D,OAAO,CAAC,eAAe,CAAqC;IAC5D,IAAW,cAAc,IAAI,UAAU,GAAG,SAAS,CAElD;IACD,IAAW,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,EAOpD;IACM,YAAY,EAAE,OAAO,CAAS;IAC9B,oBAAoB,EAAE,UAAU,EAAE,CAAM;IACxC,mBAAmB,EAAE,OAAO,CAAS;IACrC,eAAe,EAAE,eAAe,EAAE,CAAM;IAEL,QAAQ,EAAG,UAAU,CAAC;YAElD,aAAa;IA0CrB,eAAe;cAIL,kBAAkB;IAoBlC,IAAW,KAAK,IAAI,GAAG,CAEtB;IAED,IAAW,KAAK,CAAC,GAAG,EAAE,GAAG,EAQxB;IAED,IAAW,WAAW,IAAI,eAAe,GAAG,SAAS,CAEpD;IACD,IAAW,WAAW,IAAI,MAAM,CAM/B;IAGM,cAAc;IAOd,sBAAsB,EAAE,MAAM,CAAM;cAC3B,oBAAoB,CAAC,KAAK,EAAE,MAAM;cAoDlC,oBAAoB;cA4BpB,gBAAgB;IAIzB,gBAAgB,CAAC,YAAY,EAAE,UAAU;yCAtOvC,WAAW;2CAAX,WAAW;CAuPvB"}
|
|
@@ -16,27 +16,70 @@ import * as i1 from "@angular/common";
|
|
|
16
16
|
import * as i2 from "@angular/forms";
|
|
17
17
|
import * as i3 from "@progress/kendo-angular-buttons";
|
|
18
18
|
import * as i4 from "@progress/kendo-angular-inputs";
|
|
19
|
+
import * as i5 from "@progress/kendo-angular-dropdowns";
|
|
19
20
|
const _c0 = ["inputBox"];
|
|
20
|
-
function
|
|
21
|
-
const
|
|
21
|
+
function MJLinkField_Conditional_1_ul_4_li_1_Template(rf, ctx) { if (rf & 1) {
|
|
22
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
22
23
|
i0.ɵɵelementStart(0, "li", 6);
|
|
23
|
-
i0.ɵɵlistener("click", function
|
|
24
|
+
i0.ɵɵlistener("click", function MJLinkField_Conditional_1_ul_4_li_1_Template_li_click_0_listener() { const record_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onRecordSelected(record_r4)); });
|
|
24
25
|
i0.ɵɵtext(1);
|
|
25
26
|
i0.ɵɵelementEnd();
|
|
26
27
|
} if (rf & 2) {
|
|
27
|
-
const
|
|
28
|
-
const
|
|
28
|
+
const record_r4 = ctx.$implicit;
|
|
29
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
29
30
|
i0.ɵɵadvance();
|
|
30
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
31
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.RelatedEntityNameField ? record_r4.Get(ctx_r1.RelatedEntityNameField) : record_r4.PrimaryKey.ToString(), " ");
|
|
31
32
|
} }
|
|
32
|
-
function
|
|
33
|
+
function MJLinkField_Conditional_1_ul_4_Template(rf, ctx) { if (rf & 1) {
|
|
33
34
|
i0.ɵɵelementStart(0, "ul", 4);
|
|
34
|
-
i0.ɵɵtemplate(1,
|
|
35
|
+
i0.ɵɵtemplate(1, MJLinkField_Conditional_1_ul_4_li_1_Template, 2, 1, "li", 5);
|
|
35
36
|
i0.ɵɵelementEnd();
|
|
36
37
|
} if (rf & 2) {
|
|
37
|
-
const
|
|
38
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
38
39
|
i0.ɵɵadvance();
|
|
39
|
-
i0.ɵɵproperty("ngForOf",
|
|
40
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.RelatedEntityRecords);
|
|
41
|
+
} }
|
|
42
|
+
function MJLinkField_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
43
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
44
|
+
i0.ɵɵelementStart(0, "input", 1, 0);
|
|
45
|
+
i0.ɵɵtwoWayListener("ngModelChange", function MJLinkField_Conditional_1_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.RecordName, $event) || (ctx_r1.RecordName = $event); return i0.ɵɵresetView($event); });
|
|
46
|
+
i0.ɵɵelementEnd();
|
|
47
|
+
i0.ɵɵelementStart(2, "button", 2);
|
|
48
|
+
i0.ɵɵlistener("click", function MJLinkField_Conditional_1_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onClearClicked()); });
|
|
49
|
+
i0.ɵɵtext(3, "Clear");
|
|
50
|
+
i0.ɵɵelementEnd();
|
|
51
|
+
i0.ɵɵtemplate(4, MJLinkField_Conditional_1_ul_4_Template, 2, 1, "ul", 3);
|
|
52
|
+
} if (rf & 2) {
|
|
53
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
54
|
+
i0.ɵɵproperty("ngClass", ctx_r1.RecordLinked ? "record-linked" : "");
|
|
55
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.RecordName);
|
|
56
|
+
i0.ɵɵadvance(4);
|
|
57
|
+
i0.ɵɵproperty("ngIf", ctx_r1.showMatchingRecords);
|
|
58
|
+
} }
|
|
59
|
+
function MJLinkField_Conditional_2_Conditional_0_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
60
|
+
i0.ɵɵelement(0, "kendo-combobox-column", 9);
|
|
61
|
+
} if (rf & 2) {
|
|
62
|
+
const d_r6 = ctx.$implicit;
|
|
63
|
+
i0.ɵɵproperty("field", d_r6.Name)("title", d_r6.DisplayNameOrName);
|
|
64
|
+
} }
|
|
65
|
+
function MJLinkField_Conditional_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
66
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
67
|
+
i0.ɵɵelementStart(0, "kendo-multicolumncombobox", 8);
|
|
68
|
+
i0.ɵɵtwoWayListener("valueChange", function MJLinkField_Conditional_2_Conditional_0_Template_kendo_multicolumncombobox_valueChange_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.SelectedRecord, $event) || (ctx_r1.SelectedRecord = $event); return i0.ɵɵresetView($event); });
|
|
69
|
+
i0.ɵɵrepeaterCreate(1, MJLinkField_Conditional_2_Conditional_0_For_2_Template, 1, 2, "kendo-combobox-column", 9, i0.ɵɵrepeaterTrackByIdentity);
|
|
70
|
+
i0.ɵɵelementEnd();
|
|
71
|
+
} if (rf & 2) {
|
|
72
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
73
|
+
i0.ɵɵproperty("data", ctx_r1.RelatedEntityRecords)("textField", ctx_r1.RelatedEntityInfo.NameField ? ctx_r1.RelatedEntityInfo.NameField.Name : ctx_r1.RelatedEntityInfo.FirstPrimaryKey.Name)("valueField", ctx_r1.RelatedEntityInfo.FirstPrimaryKey.Name);
|
|
74
|
+
i0.ɵɵtwoWayProperty("value", ctx_r1.SelectedRecord);
|
|
75
|
+
i0.ɵɵadvance();
|
|
76
|
+
i0.ɵɵrepeater(ctx_r1.dropDownColumns);
|
|
77
|
+
} }
|
|
78
|
+
function MJLinkField_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
79
|
+
i0.ɵɵtemplate(0, MJLinkField_Conditional_2_Conditional_0_Template, 3, 4, "kendo-multicolumncombobox", 7);
|
|
80
|
+
} if (rf & 2) {
|
|
81
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
82
|
+
i0.ɵɵconditional(ctx_r1.RelatedEntityInfo ? 0 : -1);
|
|
40
83
|
} }
|
|
41
84
|
/**
|
|
42
85
|
* This component is used to automatically generate a UI for any field in a given BaseEntity object. The CodeGen tool will generate forms and form sections that
|
|
@@ -45,8 +88,9 @@ function MJLinkField_ul_5_Template(rf, ctx) { if (rf & 1) {
|
|
|
45
88
|
* components for field rendering/editing when needed.
|
|
46
89
|
*/
|
|
47
90
|
export class MJLinkField extends BaseRecordComponent {
|
|
48
|
-
constructor() {
|
|
49
|
-
super(
|
|
91
|
+
constructor(cdr) {
|
|
92
|
+
super();
|
|
93
|
+
this.cdr = cdr;
|
|
50
94
|
/**
|
|
51
95
|
* The name of the field in the entity to be rendered.
|
|
52
96
|
*/
|
|
@@ -55,37 +99,74 @@ export class MJLinkField extends BaseRecordComponent {
|
|
|
55
99
|
* For users of this component, if you already know the name of the record we are linking to, provide it here to reduce DB overhead
|
|
56
100
|
*/
|
|
57
101
|
this.RecordName = '';
|
|
102
|
+
/**
|
|
103
|
+
* The type of component to show, search is a user input field that searches for records, dropdown is a dropdown list of records. The default is 'search'. If the related entity has
|
|
104
|
+
* a small list of possible records, it is often desirable to show a dropdown list instead of a search box.
|
|
105
|
+
*/
|
|
106
|
+
this.LinkComponentType = 'Search';
|
|
58
107
|
this.RelatedEntityInfo = undefined;
|
|
108
|
+
this._SelectedRecord = undefined;
|
|
59
109
|
this.RecordLinked = false;
|
|
60
|
-
this.
|
|
110
|
+
this.RelatedEntityRecords = [];
|
|
61
111
|
this.showMatchingRecords = false;
|
|
112
|
+
this.dropDownColumns = [];
|
|
62
113
|
this.RelatedEntityNameField = '';
|
|
63
114
|
}
|
|
64
|
-
|
|
115
|
+
get SelectedRecord() {
|
|
116
|
+
return this._SelectedRecord;
|
|
117
|
+
}
|
|
118
|
+
set SelectedRecord(val) {
|
|
119
|
+
this._SelectedRecord = val;
|
|
120
|
+
if (val) {
|
|
121
|
+
this.Value = val.FirstPrimaryKey.Value;
|
|
122
|
+
}
|
|
123
|
+
else
|
|
124
|
+
this.Value = null;
|
|
125
|
+
}
|
|
126
|
+
initComponent() {
|
|
65
127
|
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
var _a;
|
|
66
129
|
if (!this.record)
|
|
67
130
|
throw new Error('record property is required');
|
|
68
131
|
if (!this.FieldName)
|
|
69
132
|
throw new Error('FieldName property is required');
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
133
|
+
const relatedEntityID = (_a = this.EntityField) === null || _a === void 0 ? void 0 : _a.RelatedEntityID;
|
|
134
|
+
const md = new Metadata();
|
|
135
|
+
if (relatedEntityID) {
|
|
136
|
+
this.RelatedEntityInfo = md.EntityByID(relatedEntityID);
|
|
137
|
+
this.cdr.detectChanges();
|
|
138
|
+
}
|
|
139
|
+
if (this.LinkComponentType === 'Search') {
|
|
140
|
+
yield this.AttemptToLinkValue();
|
|
141
|
+
if (this.inputBox) {
|
|
142
|
+
fromEvent(this.inputBox.nativeElement, 'input')
|
|
143
|
+
.pipe(debounceTime(300))
|
|
144
|
+
.subscribe(() => {
|
|
145
|
+
if (!this.RecordLinked) {
|
|
146
|
+
this.showMatchingRecords = true;
|
|
147
|
+
this.fetchMatchingRecords(this.inputBox.nativeElement.value);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
fromEvent(this.inputBox.nativeElement, 'keydown').subscribe((event) => {
|
|
151
|
+
if (this.RecordLinked && !['Backspace', 'Delete'].includes(event.key)) {
|
|
152
|
+
event.preventDefault();
|
|
153
|
+
}
|
|
154
|
+
else if (['Backspace', 'Delete'].includes(event.key)) {
|
|
155
|
+
this.RecordName = '';
|
|
156
|
+
this.Value = null;
|
|
157
|
+
this.RecordLinked = false;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
87
160
|
}
|
|
88
|
-
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
yield this.populateDropdownList();
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
ngAfterViewInit() {
|
|
168
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
169
|
+
yield this.initComponent();
|
|
89
170
|
});
|
|
90
171
|
}
|
|
91
172
|
AttemptToLinkValue() {
|
|
@@ -114,7 +195,12 @@ export class MJLinkField extends BaseRecordComponent {
|
|
|
114
195
|
}
|
|
115
196
|
set Value(val) {
|
|
116
197
|
this.record.Set(this.FieldName, val);
|
|
117
|
-
this.
|
|
198
|
+
if (this.LinkComponentType === 'Search') {
|
|
199
|
+
this.AttemptToLinkValue();
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
this.SetDropdownValue();
|
|
203
|
+
}
|
|
118
204
|
}
|
|
119
205
|
get EntityField() {
|
|
120
206
|
var _a;
|
|
@@ -135,17 +221,38 @@ export class MJLinkField extends BaseRecordComponent {
|
|
|
135
221
|
}
|
|
136
222
|
fetchMatchingRecords(query) {
|
|
137
223
|
return __awaiter(this, void 0, void 0, function* () {
|
|
138
|
-
var _a
|
|
139
|
-
const relatedEntityID = (_a = this.EntityField) === null || _a === void 0 ? void 0 : _a.RelatedEntityID;
|
|
140
|
-
const md = new Metadata();
|
|
224
|
+
var _a;
|
|
141
225
|
this.RecordLinked = false;
|
|
142
|
-
this.
|
|
143
|
-
if (
|
|
144
|
-
this.RelatedEntityInfo = md.EntityByID(relatedEntityID);
|
|
145
|
-
// do a lookup using runView for records that have the Name field that start with the query
|
|
226
|
+
this.RelatedEntityRecords = [];
|
|
227
|
+
if (this.RelatedEntityInfo) {
|
|
146
228
|
this.RelatedEntityNameField = this.RelatedEntityInfo.NameField ? this.RelatedEntityInfo.NameField.Name : '';
|
|
229
|
+
const escapedQuery = query.replace(/'/g, "''");
|
|
230
|
+
let filter = '';
|
|
231
|
+
if (!this.RelatedEntityInfo.FirstPrimaryKey.NeedsQuotes) {
|
|
232
|
+
// the pkey is a number, so let's see if the query is a number
|
|
233
|
+
if (isNaN(Number(query)) && this.RelatedEntityNameField === '') {
|
|
234
|
+
// if the query is not a number (for number pkeys) and we don't have a name field to search on, then we can't search
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// if we get here it means we either have a RelatedEntityNameField to search on or the query is a number
|
|
239
|
+
if (!isNaN(Number(query))) {
|
|
240
|
+
// if the query is a number, then we can search on the pkey
|
|
241
|
+
filter = `[${this.RelatedEntityInfo.FirstPrimaryKey.Name}] = ${query}`;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
else if (this.RelatedEntityInfo.FirstPrimaryKey.Type.trim().toLowerCase() !== 'uniqueidentifier') {
|
|
246
|
+
// the pkey is a string that is NOT a unique identifier, so we can search on it no matter what the query is, a number, not a number, whatever
|
|
247
|
+
filter = `[${this.RelatedEntityInfo.FirstPrimaryKey.Name}] = '${escapedQuery}'`;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
// we can't search on the pkey so leave it alone
|
|
251
|
+
}
|
|
147
252
|
if (this.RelatedEntityNameField) {
|
|
148
|
-
|
|
253
|
+
filter = `[${this.RelatedEntityNameField}] LIKE '${escapedQuery}%'${filter.length > 0 ? ' OR ' + filter : ''}`;
|
|
254
|
+
}
|
|
255
|
+
if (filter && filter.length > 0) {
|
|
149
256
|
const rv = new RunView();
|
|
150
257
|
const result = yield rv.RunView({
|
|
151
258
|
EntityName: this.RelatedEntityInfo.Name,
|
|
@@ -154,55 +261,90 @@ export class MJLinkField extends BaseRecordComponent {
|
|
|
154
261
|
ResultType: 'entity_object',
|
|
155
262
|
MaxRows: 5
|
|
156
263
|
});
|
|
157
|
-
if (result && ((
|
|
158
|
-
this.
|
|
264
|
+
if (result && ((_a = result.Results) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
265
|
+
this.RelatedEntityRecords = result.Results;
|
|
159
266
|
}
|
|
160
267
|
}
|
|
268
|
+
else {
|
|
269
|
+
this.RelatedEntityRecords = [{ Name: "Can't search on " + this.RelatedEntityInfo.Name + ' records' }]; // this will have the effect of a single record in the list that says "Can't search on..."
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
populateDropdownList() {
|
|
275
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
276
|
+
if (this.RelatedEntityInfo) {
|
|
277
|
+
this.dropDownColumns = this.RelatedEntityInfo.Fields.filter(f => f.DefaultInView || f.IsPrimaryKey || f.IsNameField);
|
|
278
|
+
this.cdr.detectChanges();
|
|
279
|
+
// run a view to get the records
|
|
280
|
+
const rv = new RunView();
|
|
281
|
+
const result = yield rv.RunView({
|
|
282
|
+
EntityName: this.RelatedEntityInfo.Name,
|
|
283
|
+
ExtraFilter: '',
|
|
284
|
+
OrderBy: this.RelatedEntityNameField,
|
|
285
|
+
ResultType: 'entity_object',
|
|
286
|
+
});
|
|
287
|
+
if (result && result.Success) {
|
|
288
|
+
this.RelatedEntityRecords = result.Results;
|
|
289
|
+
// look for a match between the records we have, finding a match between our this.Value and the pkey of the record
|
|
290
|
+
const match = this.RelatedEntityRecords.find(r => r.FirstPrimaryKey.Value === this.Value);
|
|
291
|
+
if (match) {
|
|
292
|
+
this.SelectedRecord = match;
|
|
293
|
+
this.SetDropdownValue();
|
|
294
|
+
}
|
|
295
|
+
this.cdr.detectChanges();
|
|
296
|
+
}
|
|
161
297
|
}
|
|
162
298
|
});
|
|
163
299
|
}
|
|
300
|
+
SetDropdownValue() {
|
|
301
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
302
|
+
});
|
|
303
|
+
}
|
|
164
304
|
onRecordSelected(linkedRecord) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
305
|
+
if (linkedRecord.EntityInfo) {
|
|
306
|
+
this.SelectedRecord = linkedRecord;
|
|
307
|
+
this.RecordName = this.RelatedEntityNameField ? linkedRecord.Get(this.RelatedEntityNameField) : linkedRecord.PrimaryKey.ToString();
|
|
308
|
+
this.RecordLinked = true;
|
|
309
|
+
this.showMatchingRecords = false;
|
|
310
|
+
this.record.Set(this.FieldName, linkedRecord.FirstPrimaryKey.Value);
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
// this means that we really don't have a selected record and we were just showing the "Can't search on..." record
|
|
314
|
+
this.showMatchingRecords = false;
|
|
315
|
+
this.RecordLinked = false;
|
|
316
|
+
this.RecordName = '';
|
|
317
|
+
}
|
|
318
|
+
this.cdr.detectChanges();
|
|
169
319
|
}
|
|
170
320
|
}
|
|
171
|
-
MJLinkField.ɵfac =
|
|
321
|
+
MJLinkField.ɵfac = function MJLinkField_Factory(t) { return new (t || MJLinkField)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
172
322
|
MJLinkField.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJLinkField, selectors: [["mj-link-field"]], viewQuery: function MJLinkField_Query(rf, ctx) { if (rf & 1) {
|
|
173
|
-
i0.ɵɵviewQuery(_c0,
|
|
323
|
+
i0.ɵɵviewQuery(_c0, 5);
|
|
174
324
|
} if (rf & 2) {
|
|
175
325
|
let _t;
|
|
176
326
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.inputBox = _t.first);
|
|
177
|
-
} }, inputs: { record: "record", FieldName: "FieldName", RecordName: "RecordName" }, features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
178
|
-
|
|
179
|
-
i0.ɵɵ
|
|
180
|
-
i0.ɵɵtwoWayListener("ngModelChange", function MJLinkField_Template_input_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.RecordName, $event) || (ctx.RecordName = $event); return i0.ɵɵresetView($event); });
|
|
181
|
-
i0.ɵɵelementEnd();
|
|
182
|
-
i0.ɵɵelementStart(3, "button", 2);
|
|
183
|
-
i0.ɵɵlistener("click", function MJLinkField_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onClearClicked()); });
|
|
184
|
-
i0.ɵɵtext(4, "Clear");
|
|
185
|
-
i0.ɵɵelementEnd();
|
|
186
|
-
i0.ɵɵtemplate(5, MJLinkField_ul_5_Template, 2, 1, "ul", 3);
|
|
327
|
+
} }, inputs: { record: "record", FieldName: "FieldName", RecordName: "RecordName", LinkComponentType: "LinkComponentType" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 3, vars: 1, consts: [["inputBox", ""], ["type", "text", "kendoTextBox", "", 1, "input-box", 3, "ngModelChange", "ngClass", "ngModel"], ["kendoButton", "", 3, "click"], ["class", "matching-records", 4, "ngIf"], [1, "matching-records"], [3, "click", 4, "ngFor", "ngForOf"], [3, "click"], [3, "data", "textField", "valueField", "value"], [3, "valueChange", "data", "textField", "valueField", "value"], [3, "field", "title"]], template: function MJLinkField_Template(rf, ctx) { if (rf & 1) {
|
|
328
|
+
i0.ɵɵelementStart(0, "div");
|
|
329
|
+
i0.ɵɵtemplate(1, MJLinkField_Conditional_1_Template, 5, 3)(2, MJLinkField_Conditional_2_Template, 1, 1);
|
|
187
330
|
i0.ɵɵelementEnd();
|
|
188
331
|
} if (rf & 2) {
|
|
189
332
|
i0.ɵɵadvance();
|
|
190
|
-
i0.ɵɵ
|
|
191
|
-
|
|
192
|
-
i0.ɵɵadvance(4);
|
|
193
|
-
i0.ɵɵproperty("ngIf", ctx.showMatchingRecords);
|
|
194
|
-
} }, dependencies: [i1.NgClass, i1.NgForOf, i1.NgIf, i2.DefaultValueAccessor, i2.NgControlStatus, i2.NgModel, i3.ButtonComponent, i4.TextBoxDirective], styles: [".record-linked[_ngcontent-%COMP%] {\n color: darkblue;\n text-decoration: underline;\n}\n\n.input-box[_ngcontent-%COMP%] {\n width: 400px;\n}\n\nbutton[_ngcontent-%COMP%] {\n width: 50px;\n}\n\n\n.matching-records[_ngcontent-%COMP%] {\n width: 400px;\n list-style-type: none;\n margin: 0;\n padding: 0;\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid #ccc;\n}\n\n.matching-records[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n padding: 8px;\n cursor: pointer;\n}\n\n.matching-records[_ngcontent-%COMP%] li[_ngcontent-%COMP%]:hover {\n background-color: #f0f0f0;\n}"] });
|
|
333
|
+
i0.ɵɵconditional(ctx.LinkComponentType === "Search" ? 1 : 2);
|
|
334
|
+
} }, dependencies: [i1.NgClass, i1.NgForOf, i1.NgIf, i2.DefaultValueAccessor, i2.NgControlStatus, i2.NgModel, i3.ButtonComponent, i4.TextBoxDirective, i5.MultiColumnComboBoxComponent, i5.ComboBoxColumnComponent], styles: [".record-linked[_ngcontent-%COMP%] {\n color: darkblue;\n text-decoration: underline;\n}\n\n.input-box[_ngcontent-%COMP%] {\n width: 400px;\n}\n\nbutton[_ngcontent-%COMP%] {\n width: 50px;\n}\n\n\n.matching-records[_ngcontent-%COMP%] {\n width: 400px;\n list-style-type: none;\n margin: 0;\n padding: 0;\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid #ccc;\n}\n\n.matching-records[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n padding: 8px;\n cursor: pointer;\n}\n\n.matching-records[_ngcontent-%COMP%] li[_ngcontent-%COMP%]:hover {\n background-color: #f0f0f0;\n}"] });
|
|
195
335
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJLinkField, [{
|
|
196
336
|
type: Component,
|
|
197
|
-
args: [{ selector: 'mj-link-field', template: "
|
|
198
|
-
}],
|
|
337
|
+
args: [{ selector: 'mj-link-field', template: "<div>\n @if (LinkComponentType === 'Search') {\n <input \n #inputBox\n type=\"text\" \n class=\"input-box\" \n [ngClass]=\"RecordLinked ? 'record-linked' : ''\" \n [(ngModel)]=\"RecordName\" \n kendoTextBox \n />\n <button kendoButton (click)=\"onClearClicked()\">Clear</button>\n\n <ul *ngIf=\"showMatchingRecords\" class=\"matching-records\">\n <li *ngFor=\"let record of RelatedEntityRecords\" (click)=\"onRecordSelected(record)\">\n {{ RelatedEntityNameField ? record.Get(RelatedEntityNameField) : record.PrimaryKey.ToString() }}\n </li>\n </ul>\n }\n @else {\n @if (RelatedEntityInfo) {\n <kendo-multicolumncombobox \n [data]=\"RelatedEntityRecords\"\n [textField]=\"RelatedEntityInfo.NameField ? RelatedEntityInfo.NameField.Name : RelatedEntityInfo.FirstPrimaryKey.Name\"\n [valueField]=\"RelatedEntityInfo.FirstPrimaryKey.Name\"\n [(value)]=\"SelectedRecord\"\n >\n @for (d of dropDownColumns; track d) {\n <kendo-combobox-column\n [field]=\"d.Name\"\n [title]=\"d.DisplayNameOrName\"\n >\n </kendo-combobox-column>\n }\n </kendo-multicolumncombobox> \n }\n }\n</div>", styles: [".record-linked {\n color: darkblue;\n text-decoration: underline;\n}\n\n.input-box {\n width: 400px;\n}\n\nbutton {\n width: 50px;\n}\n\n\n.matching-records {\n width: 400px;\n list-style-type: none;\n margin: 0;\n padding: 0;\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid #ccc;\n}\n\n.matching-records li {\n padding: 8px;\n cursor: pointer;\n}\n\n.matching-records li:hover {\n background-color: #f0f0f0;\n}\n"] }]
|
|
338
|
+
}], () => [{ type: i0.ChangeDetectorRef }], { record: [{
|
|
199
339
|
type: Input
|
|
200
340
|
}], FieldName: [{
|
|
201
341
|
type: Input
|
|
202
342
|
}], RecordName: [{
|
|
203
343
|
type: Input
|
|
344
|
+
}], LinkComponentType: [{
|
|
345
|
+
type: Input
|
|
204
346
|
}], inputBox: [{
|
|
205
347
|
type: ViewChild,
|
|
206
|
-
args: ['inputBox', { static:
|
|
348
|
+
args: ['inputBox', { static: false }]
|
|
207
349
|
}] }); })();
|
|
208
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJLinkField, { className: "MJLinkField"
|
|
350
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJLinkField, { className: "MJLinkField" }); })();
|
|
@@ -75,4 +75,4 @@ SectionLoaderComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: Sect
|
|
|
75
75
|
type: ViewChild,
|
|
76
76
|
args: ['container', { read: ViewContainerRef }]
|
|
77
77
|
}] }); })();
|
|
78
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SectionLoaderComponent, { className: "SectionLoaderComponent"
|
|
78
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SectionLoaderComponent, { className: "SectionLoaderComponent" }); })();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-base-forms",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "MemberJunction: Angular Base Form Components",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -25,21 +25,21 @@
|
|
|
25
25
|
"@angular/router": "18.0.2"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@memberjunction/global": "
|
|
29
|
-
"@memberjunction/core": "
|
|
30
|
-
"@memberjunction/ng-code-editor": "
|
|
31
|
-
"@memberjunction/ng-shared": "
|
|
32
|
-
"@memberjunction/ng-tabstrip": "
|
|
33
|
-
"@memberjunction/ng-link-directives": "
|
|
34
|
-
"@memberjunction/ng-container-directives": "
|
|
35
|
-
"@memberjunction/ng-record-changes": "
|
|
36
|
-
"@memberjunction/ng-base-types": "
|
|
28
|
+
"@memberjunction/global": "2.0.0",
|
|
29
|
+
"@memberjunction/core": "2.0.0",
|
|
30
|
+
"@memberjunction/ng-code-editor": "2.0.0",
|
|
31
|
+
"@memberjunction/ng-shared": "2.0.0",
|
|
32
|
+
"@memberjunction/ng-tabstrip": "2.0.0",
|
|
33
|
+
"@memberjunction/ng-link-directives": "2.0.0",
|
|
34
|
+
"@memberjunction/ng-container-directives": "2.0.0",
|
|
35
|
+
"@memberjunction/ng-record-changes": "2.0.0",
|
|
36
|
+
"@memberjunction/ng-base-types": "2.0.0",
|
|
37
37
|
"@progress/kendo-angular-buttons": "16.2.0",
|
|
38
38
|
"@progress/kendo-angular-dropdowns": "16.2.0",
|
|
39
39
|
"@progress/kendo-angular-inputs": "16.2.0",
|
|
40
40
|
"@progress/kendo-angular-dateinputs": "16.2.0",
|
|
41
41
|
"@progress/kendo-angular-dialog": "16.2.0",
|
|
42
|
-
"ngx-markdown": "18.0.0",
|
|
42
|
+
"ngx-markdown": "^18.0.0",
|
|
43
43
|
"rxjs": "^7.8.1",
|
|
44
44
|
"tslib": "^2.3.0"
|
|
45
45
|
},
|