FlexFieldEditor= function( editorOptions ) { let instance = this; instance.rootElement = null; instance.data = editorOptions.data; instance.dataChanged = false; instance.onSaved = editorOptions.onSaved; if( ! instance.onSaved ) { instance.onSaved = function() { } } instance.onCancelled = editorOptions.onCancelled; if( ! instance.onCancelled ) { instance.onCancelled = function() { } } instance.flexType = "standard"; if( editorOptions.flexType ) { instance.flexType = editorOptions.flexType } instance.fieldId = instance.data.fieldId; let fieldData = $.extend( true, {}, instance.data ); delete fieldData.config; let fieldConfig = {}; if( instance.data.config ) { let configSplit = instance.data.config.split(","); configSplit.forEach( function( co ) { let avp = co.split( "=" ); fieldConfig[avp[0]] = null; if( avp.length > 0 ) { fieldConfig[avp[0]] = avp[1]; } }) } instance.rootElement = $("
"); instance.lookupValuesDataGrid = null; let leftItems = [ { dataField : "label", editorType : "dxTextBox", isRequired : true }, { dataField : "sortRank", editorType : "dxNumberBox", isRequired : true, editorOptions : { width : 40, showSpinButtons : false, min : 1, max : 999 } }, { dataField : "active", editorType : "dxRadioGroup", editorOptions : { layout : "horizontal", items : [ { text : "Yes", value : "Y" }, { text : "No", value : "N" } ], valueExpr : "value" } }, { dataField : "required", editorType : "dxRadioGroup", editorOptions : { layout : "horizontal", items : [ { text : "Yes", value : "Y" }, { text : "No", value : "N" } ], valueExpr : "value" } }, { dataField : "searchable", visible : instance.flexType == "standard" ? true : false, editorType : "dxRadioGroup", editorOptions : { disabled : fieldData.type == "CHECKBOX" || fieldData.type == "SELECT" || fieldData.type == "RADIO" ? false : true, layout : "horizontal", items : [ { text : "Yes", value : "Y" }, { text : "No", value : "N" } ], valueExpr : "value" } } ]; if( instance.flexType != "standard" ) { let sourceFieldStore = Fse.Data.newDataSource( { object : "WRK.flexFields", keyField : "fieldId", paginate : false, objectParams : { domain : instance.data.domain, category : instance.data.category, type : "SELECT,RADIO" } }).store(); let sourceFieldDataSourceConfig = { store : sourceFieldStore, paginate : false } if( instance.data.fieldId ) { sourceFieldDataSourceConfig.filter = [ "fieldId", "<>", instance.data.fieldId ]; } let sourceFieldValueDS = null; if( instance.data.sourceFieldId ) { sourceFieldValueDS = Fse.Data.newDataSource( { object : "WRK.flexFieldLookupValues", paginate : false, keyField : "text", objectParams : { domain : instance.data.domain, category : instance.data.category, fieldId : instance.data.sourceFieldId } }) } console.log( "SourceFieldValueDS", sourceFieldValueDS ); leftItems.push( { itemType : "empty" }, { itemType : "group", colCount : 2, items : [ { dataField : "sourceFieldId", label : { text : "Conditional Field" }, editorType : "dxSelectBox", editorOptions : { placeholder : "select field", showClearButton : true, dataSource : sourceFieldDataSourceConfig, displayExpr : "label", valueExpr : "fieldId" } }, { dataField : "sourceFieldValue", label : { text : "Conditional Value" }, editorType : "dxSelectBox", editorOptions : { placeholder : "select value", showClearButton : true, displayExpr : "text", valueExpr : "text", dataSource : sourceFieldValueDS } } ] }) } let rightItems = []; if( fieldData.type == "TEXT" || fieldData.type == "TEXTAREA" ) { rightItems.push( { dataField : "maxLength", editorType : "dxNumberBox", isRequired : true, editorOptions : { min : 1, max : 1000, width : 50 } }); rightItems.push( { dataField : "format", editorType : "dxSelectBox", editorOptions : { displayExpr : "format", valueExpr : "format", width : 100, dataSource : { store : { type : "array", data : [ { format : "string"}, { format : "email" }, { format : "url" }, { format : "date" }, { format : "decimal" }, { format : "phone" } ], key : "format" }} } }); } if( fieldData.type == "TEXTAREA" ) { fieldData.cols = parseInt( fieldConfig.cols ); fieldData.rows = parseInt( fieldConfig.rows ); rightItems.push ( { dataField : "rows", editorType : "dxNumberBox", isRequired : true, editorOptions : { min : 1, max : 10, width : 40 } }, { dataField : "cols", label : { text : "Columns" }, editorType : "dxNumberBox", isRequired : true, editorOptions : { min : 1, max : 10, width : 40 } } ); } else if ( fieldData.type == "TEXT" ) { fieldData.size = parseInt( fieldConfig.size ); rightItems.push( { dataField : "size", label : { text : "Field Width" }, editorType : "dxNumberBox", isRequired : true, editorOptions : { min : 1, max : 100, width : 40 } }) } if( fieldData.type == "RADIO" || fieldData.type == "SELECT" || fieldData.type == "CHECKBOX" ) { let lookupColumns = [ // these are auto generated now { dataField : "value", caption : "Code", validationRules: [{ type: 'required' }], editorOptions : { maxLength : 75 } }, { dataField : "text", caption : "Display", validationRules: [{ type: 'required' }], editorOptions : { maxLength : 75 } }, { dataField : "sortRank", visible : true, caption : "Order", width : 70, dataType : "number", format : "fixedPoint", validationRules: [{ type: 'required' }], editorOptions : { min : 1, max : 999, showSpinControls : false } } ]; if( instance.flexType != "standard" ) { let sourceFieldStore = Fse.Data.newDataSource( { object : "WRK.flexFields", keyField : "fieldId", paginate : false, objectParams : { domain : instance.data.domain, category : instance.data.category, type : "SELECT,RADIO" } }).store(); let sourceFieldDataSourceConfig = { store : sourceFieldStore, paginate : false } if( instance.data.fieldId ) { sourceFieldDataSourceConfig.filter = [ "fieldId", "<>", instance.data.fieldId ]; } lookupColumns.push( { dataField : "sourceFieldId", caption : "Conditional Field", editorType : "dxSelectBox", lookup : { dataSource : sourceFieldDataSourceConfig, displayExpr : "label", valueExpr : "fieldId", allowClearing : true }, editorOptions : { placeholder : "select field" }, setCellValue: function(newData, value) { this.defaultSetCellValue(newData, value); } }, { dataField : "sourceFieldValue", caption : "Conditional Label", editorType : "dxSelectBox", editorOptions :{ placeholder : "select value", displayExpr : "text", valueExpr : "text" } } ) } rightItems.push( { dataField : "lookupValues", label : { visible : false }, template : function( options ) { let form = options.component; let formData = form.option( "formData" ); let lookupValues = formData.lookupValues; instance.lookupValuesDataGrid = $("
").dxDataGrid( { height : 200, scrolling : { mode : "virtual" }, dataSource : { store : { type : "array", data : lookupValues, key : "value" } }, editing : { allowUpdating : true, allowAdding : true, newRowPosition : "last", allowDeleting : true, mode : "row", useIcons : true, editRowKey : "value", texts : { addRow : "Add a possible selection", deleteRow : "Delete possible selection", editRow : "Edit possible selection" } }, showBorders : true, rowAlternationEnabled : true, columns : lookupColumns, onEditorPreparing : function( e ) { if( e.dataField == "sourceFieldValue") { if( e.row.data.sourceFieldId ) { e.editorOptions.dataSource = Fse.Data.newDataSource( { object : "WRK.flexFieldLookupValues", paginate : false, keyField : "text", objectParams : { domain : instance.data.domain, category : instance.data.category, fieldId : e.row.data.sourceFieldId } }) e.editorOptions.value = e.value; } else { e.editorOptions.dataSource = null; e.editorOptions.value = null; } } console.log( e ); }, onCellClick : function( e ) { if( e.rowType != "data" ) return; if( e.column.dataField != "text" ) return; let ready = $.Deferred(); if( e.component.hasEditData() ) { e.component.saveEditData().done( function() { ready.resolve(); }) } else { ready.resolve(); } // if( editRowKey ) return; // already editing ready.done( function() { e.component.editRow( e.rowIndex ); }) }, onInitNewRow : function( e ) { // goal is to assign the next sortRank value let maxSortRank = 0; let formData = form.option( "formData" ); let formLookupValues = formData.lookupValues; if( formLookupValues ) { formLookupValues.forEach( function( lv ) { if( lv.sortRank > maxSortRank ) { maxSortRank = lv.sortRank; } }) } let valueSeq = ( new Date() ).getTime(); let newValue = `F${formData.fieldId}_${valueSeq}`; let newSortRank = maxSortRank; if( newSortRank == 0 ) { newSortRank = 10; // start at 10 } else { // go to the next highest multiple of 10 newSortRank = newSortRank - ( newSortRank % 10 ) + 10; if( newSortRank == maxSortRank ) { newSortRank += 10; } } e.data.sortRank = newSortRank; e.data.value = newValue; }, onSaved : function( e ) { let savedKey = e.changes[e.changes.length - 1 ].key; let items = e.component.getDataSource().items(); form.updateData( { "lookupValues": items } ); let vr = e.component.getVisibleRows(); let currentKey = null; let nextRow = null; vr.forEach( function( row ) { if( !nextRow && currentKey ) { nextRow = row; console.log( "next row", row ); } if( row.key == savedKey ) { currentKey = savedKey; } }) if( nextRow ) { e.component.editRow( nextRow.rowIndex ); } }, onRowInserted : function( e ) { e.component.addRow(); }, onToolbarPreparing : function( e ) { if( ! e.toolbarOptions.items ) { e.toolbarOptions.items = []; } e.toolbarOptions.items.push( { location : "before", template : function() { return $("
").text( "Possible Selections"); } }) } }).dxDataGrid( "instance" ); if( ! lookupValues || lookupValues.length == 0 ) { let p = instance.lookupValuesDataGrid.addRow(); p.done( function( addRow ) { console.log( "addRow", addRow ); }) } return instance.lookupValuesDataGrid.element(); } }, { dataField : "lookupValueSortMode", editorType : "dxRadioGroup", label : { text : "Reorder (on save)" }, editorOptions : { layout : "horizontal", valueExpr : "value", displayExpr : "text", items : [ { value : "alpha", text : "by Alpha" } , { value : "numeric", text : "by Numeric" }, { value : "manual", text : "using Order" } ] } } ) } instance.form = $("
").dxForm( { colCount : 2, items : [ { itemType : "group", items : leftItems }, { itemType : "group", items : rightItems } ], formData : fieldData, onFieldDataChanged : function( e ) { console.log( e ); if( e.dataField == "sourceFieldId" ) { let sourceFieldValueEditor = e.component.getEditor( "sourceFieldValue" ); let dataSource = null; if( e.value ) { dataSource = Fse.Data.newDataSource( { object : "WRK.flexFieldLookupValues", paginate : false, keyField : "value", objectParams : { domain : instance.data.domain, category : instance.data.category, fieldId : e.value } }) } sourceFieldValueEditor.option( "dataSource", dataSource ); e.component.updateData( "sourceFieldValue", null ); } instance.dataChanged = true; instance.saveButton.option( { disabled : false }) } }).dxForm( "instance") instance.saveButton = $("
").dxButton( { text : "Save Field", disabled : true, type : "default", onClick : function( e ) { /* if( instance.lookupValuesDataGrid && instance.lookupValuesDataGrid.hasEditData() ) { alert( "You must save or cancel the selection you are editing before saving.") return; } */ let vr = instance.form.validate(); if( ! vr.isValid ) { return; } instance.save(); } }).dxButton( "instance" ); instance.toolbar = $("
").dxToolbar( { items : [ { location : "after", widget : "dxButton", options : { text : "Cancel", onClick : function( e ) { instance.onCancelled(); } } }, { location : "after", template : function() { return instance.saveButton.element(); } } ] }).dxToolbar( "instance" ); instance.rootElement .append( instance.form.element() ) .append( instance.toolbar.element().css( { "margin-top" : "5px" }) ); } FlexFieldEditor.prototype.constructor = FlexFieldEditor; FlexFieldEditor.prototype.element = function() { return this.rootElement; } FlexFieldEditor.prototype.isDirty = function() { return this.dataChanged; } FlexFieldEditor.prototype.save = function() { let instance = this; let flexFieldData = instance.form.option( "formData" ); Fse.Ajax.performAction( { object : "WRK.saveFlexField", data : flexFieldData }).done( function() { instance.dataChanged = false; instance.saveButton.option( { "disabled" : true } ) Fse.UI.toast( `Field Saved`, "success", 1000 ); instance.onSaved(); }) }