import { extend } from '@syncfusion/ej2-base' ; import { remove , isNullOrUndefined } from '@syncfusion/ej2-base' ; import { IGrid , NotifyArgs , EditEventArgs , AddEventArgs , SaveEventArgs } from '../base/interface' ; import { parentsUntil , refreshForeignData , getObject } from '../base/util' ; import * as events from '../base/constant' ; import { EditRender } from '../renderer/edit-renderer' ; import { RowRenderer } from '../renderer/row-renderer' ; import { Row } from '../models/row' ; import { ServiceLocator } from '../services/service-locator' ; import { Column } from '../models/column' ; import { ReturnType } from '../base/type' ; import { FormValidator } from '@syncfusion/ej2-inputs' ; import { DataUtil } from '@syncfusion/ej2-data' ; hidden export class NormalEdit { protected parent : IGrid ; protected serviceLocator : ServiceLocator ; protected renderer : EditRender ; public formObj : FormValidator ; protected previousData : Object ; private editRowIndex : number ; private rowIndex : number ; private addedRowIndex : number ; private uid : string ; private args : EditEventArgs = { } ; constructor ( parent ? , serviceLocator ? , renderer ? ) { this . parent = parent ; this . renderer = renderer ; this . serviceLocator = serviceLocator ; this . addEventListener ( ) ; } protected clickHandler ( e ) { let target = e . target as Element ; let gObj = this . parent ; if ( ( ( ( parentsUntil ( target , 'e-gridcontent' ) && parentsUntil ( parentsUntil ( target , 'e-gridcontent' ) , 'e-grid' ) . id === gObj . element . id ) ) || ( gObj . frozenRows && parentsUntil ( target , 'e-headercontent' ) ) ) && ! parentsUntil ( target , 'e-unboundcelldiv' ) ) { this . rowIndex = parentsUntil ( target , 'e-rowcell' ) ? parseInt ( target . parentElement . getAttribute ( 'aria-rowindex' ) , 10 ) : - 1 ; if ( gObj . isEdit ) { gObj . editModule . endEdit ( ) ; } } } protected dblClickHandler ( e ) { if ( parentsUntil ( e . target as Element , 'e-rowcell' ) && this . parent . editSettings . allowEditOnDblClick ) { this . parent . editModule . startEdit ( parentsUntil ( e . target as Element , 'e-row' ) as HTMLTableRowElement ) ; } } return { void } hidden public editComplete ( e ) { this . parent . isEdit = false ; switch ( e . requestType as string ) { case 'save' : if ( ! ( this . parent . isCheckBoxSelection || this . parent . selectionSettings . type === 'Multiple' ) || ( ! this . parent . isPersistSelection ) ) { this . parent . selectRow ( 0 ) ; } this . parent . trigger ( events . actionComplete , extend ( e , { requestType : 'save' , type : events . actionComplete } ) ) ; break ; case 'delete' : this . parent . trigger ( events . actionComplete , extend ( e , { requestType : 'delete' , type : events . actionComplete } ) ) ; this . parent . selectRow ( this . editRowIndex ) ; break ; } } protected startEdit ( tr ) { let gObj = this . parent ; let primaryKeys = gObj . getPrimaryKeyFieldNames ( ) ; let primaryKeyValues = [ ] ; this . rowIndex = this . editRowIndex = parseInt ( tr . getAttribute ( 'aria-rowindex' ) , 10 ) ; this . previousData = gObj . getCurrentViewRecords ( ) [ this . rowIndex ] ; for ( let i = 0 ; i < primaryKeys . length ; i ++ ) { primaryKeyValues . push ( this . previousData [ primaryKeys [ i ] ] ) ; } this . uid = tr . getAttribute ( 'data-uid' ) ; let rowObj = gObj . getRowObjectFromUID ( this . uid ) ; let args = { row : tr , primaryKey : primaryKeys , primaryKeyValue : primaryKeyValues , requestType : 'beginEdit' , rowData : this . previousData , rowIndex : this . rowIndex , type : 'edit' , cancel : false , foreignKeyData : rowObj && rowObj . foreignKeyData } ; gObj . trigger ( events . beginEdit , args ) ; args . type = 'actionBegin' ; gObj . trigger ( events . actionBegin , args ) ; if ( args . cancel ) { return ; } gObj . isEdit = true ; if ( gObj . editSettings . mode !== 'Dialog' ) { gObj . clearSelection ( ) ; } if ( gObj . editSettings . mode === 'Dialog' ) { ( < { selectionModule ? : { preventFocus : boolean ; } ; } > gObj ) . selectionModule . preventFocus = true ; args . row . classList . add ( 'e-dlgeditrow' ) ; } this . renderer . update ( args ) ; this . uid = tr . getAttribute ( 'data-uid' ) ; gObj . editModule . applyFormValidation ( ) ; args . type = 'actionComplete' ; gObj . trigger ( events . actionComplete , args ) ; this . args = args ; if ( this . parent . allowTextWrap ) { this . parent . notify ( events . freezeRender , { case : 'textwrap' } ) ; } } protected updateRow ( index , data ) { let gObj = this . parent ; let args = { requestType : 'save' , type : events . actionBegin , data : data , cancel : false , previousData : gObj . getCurrentViewRecords ( ) [ index ] } ; gObj . showSpinner ( ) ; gObj . notify ( events . updateData , args ) ; gObj . refresh ( ) ; } private editFormValidate ( ) { let gObj = this . parent ; let form1 = gObj . editModule . formObj . validate ( ) ; let form2 = gObj . editModule . mFormObj ? gObj . editModule . mFormObj . validate ( ) : true ; return ( form1 && form2 ) ; } protected endEdit ( ) { let gObj = this . parent ; if ( ! this . parent . isEdit || ! this . editFormValidate ( ) ) { return ; } let editedData = extend ( { } , { } , this . previousData , true ) ; let args = extend ( this . args , { requestType : 'save' , type : events . actionBegin , data : editedData , cancel : false , previousData : this . previousData , selectedRow : gObj . selectedRowIndex , foreignKeyData : { } } ) ; editedData = gObj . editModule . getCurrentEditedData ( gObj . element . querySelector ( '.e-gridform' ) , editedData ) ; if ( gObj . getFrozenColumns ( ) && gObj . editSettings . mode === 'Normal' ) { let mForm = gObj . element . querySelector ( '.e-movableheader' ) . querySelector ( '.e-gridform' ) ; if ( gObj . frozenRows && mForm ) { editedData = gObj . editModule . getCurrentEditedData ( mForm , editedData ) ; } else { editedData = gObj . editModule . getCurrentEditedData ( gObj . element . querySelector ( '.e-movablecontent' ) . querySelector ( '.e-gridform' ) , editedData ) ; } } if ( gObj . element . querySelectorAll ( '.e-editedrow' ) . length ) { args . action = 'edit' ; gObj . trigger ( events . actionBegin , args ) ; if ( args . cancel ) { return ; } gObj . showSpinner ( ) ; gObj . notify ( events . updateData , args ) ; } else { args . action = 'add' ; args . selectedRow = 0 ; args . index = this . addedRowIndex ; gObj . notify ( events . modelChanged , args ) ; this . addedRowIndex = null ; if ( args . cancel ) { return ; } } } private destroyElements ( ) { let gObj = this . parent ; gObj . editModule . destroyWidgets ( ) ; gObj . editModule . destroyForm ( ) ; this . parent . notify ( events . dialogDestroy , { } ) ; } private editHandler ( args ) { if ( args . promise ) { args . promise . then ( ( e ) => this . edSucc ( e , args ) ) . catch ( ( e ) => this . edFail ( e ) ) ; } else { this . editSuccess ( args . data , args ) ; } } private edSucc ( e , args ) { this . editSuccess ( e , args ) ; } private edFail ( e ) { this . editFailure ( e ) ; } private updateCurrentViewData ( data ) { this . parent . getCurrentViewRecords ( ) [ this . editRowIndex ] = data ; } private requestSuccess ( args ) { if ( this . parent . editModule . formObj && ! this . parent . editModule . formObj . isDestroyed ) { this . destroyElements ( ) ; this . stopEditStatus ( ) ; if ( this . parent . editSettings . mode === 'Dialog' && ( < { action ? : string ; } > args ) . action !== 'add' ) { this . parent . element . querySelector ( '.e-dlgeditrow' ) . classList . remove ( 'e-dlgeditrow' ) ; } } } private editSuccess ( e , args ) { if ( ! isNullOrUndefined ( e ) ) { args . data = e ; } this . requestSuccess ( args ) ; this . parent . trigger ( events . beforeDataBound , args ) ; args . type = events . actionComplete ; this . parent . isEdit = false ; this . refreshRow ( args . data ) ; this . updateCurrentViewData ( args . data ) ; this . parent . trigger ( events . actionComplete , args ) ; if ( ! ( this . parent . isCheckBoxSelection || this . parent . selectionSettings . type === 'Multiple' ) || ( ! this . parent . isPersistSelection ) ) { if ( this . parent . editSettings . mode !== 'Dialog' ) { this . parent . selectRow ( this . rowIndex > - 1 ? this . rowIndex : this . editRowIndex ) ; } } this . parent . hideSpinner ( ) ; } private editFailure ( e ) { this . parent . trigger ( events . actionFailure , e ) ; this . parent . hideSpinner ( ) ; } private refreshRow ( data ) { let frzCols = this . parent . getFrozenColumns ( ) ; let row = new RowRenderer < Column > ( this . serviceLocator , null , this . parent ) ; let rowObj = this . parent . getRowObjectFromUID ( this . uid ) ; if ( rowObj ) { rowObj . changes = data ; refreshForeignData ( rowObj , this . parent . getForeignKeyColumns ( ) , rowObj . changes ) ; row . refresh ( rowObj , this . parent . getColumns ( ) as Column [ ] , true ) ; if ( frzCols ) { let uid ; let tr = this . parent . element . querySelector ( '[data-uid=' + rowObj . uid + ']' ) ; if ( ( parentsUntil ( tr , 'e-frozencontent' ) ) || ( parentsUntil ( tr , 'e-frozenheader' ) ) ) { uid = this . parent . getMovableRows ( ) [ rowObj . index ] . getAttribute ( 'data-uid' ) ; } else { uid = this . parent . getRows ( ) [ rowObj . index ] . getAttribute ( 'data-uid' ) ; } rowObj = this . parent . getRowObjectFromUID ( uid ) ; rowObj . changes = data ; row . refresh ( rowObj , this . parent . columns as Column [ ] , true ) ; } } } protected closeEdit ( ) { if ( ! this . parent . isEdit ) { return ; } let gObj = this . parent ; let args = extend ( this . args , { requestType : 'cancel' , type : events . actionBegin , data : this . previousData , selectedRow : gObj . selectedRowIndex } ) as { data : Object ; requestType : string ; selectedRow : Number ; type : string ; } ; gObj . trigger ( events . actionBegin , args ) ; if ( this . parent . editSettings . mode === 'Dialog' ) { this . parent . notify ( events . dialogDestroy , { } ) ; } gObj . isEdit = false ; this . stopEditStatus ( ) ; args . type = events . actionComplete ; if ( gObj . editSettings . mode !== 'Dialog' ) { this . refreshRow ( args . data ) ; } if ( gObj . getContentTable ( ) . querySelector ( 'tr.e-emptyrow' ) && ! gObj . getContentTable ( ) . querySelector ( 'tr.e-row' ) ) { gObj . getContentTable ( ) . querySelector ( 'tr.e-emptyrow' ) . classList . remove ( 'e-hide' ) ; } if ( gObj . editSettings . mode !== 'Dialog' ) { gObj . selectRow ( this . rowIndex ) ; } gObj . trigger ( events . actionComplete , args ) ; } protected addRecord ( data ? , index ? ) { let gObj = this . parent ; this . addedRowIndex = index = ! isNullOrUndefined ( index ) ? index : 0 ; if ( data ) { gObj . notify ( events . modelChanged , { requestType : 'save' , type : events . actionBegin , data : data , selectedRow : 0 , action : 'add' , index : index } ) ; return ; } if ( gObj . isEdit ) { return ; } this . previousData = { } ; this . uid = '' ; ( < Column [ ] > gObj . columns ) . forEach ( ( col ) => { if ( col . field ) { DataUtil . setValue ( col . field , col . defaultValue , this . previousData ) ; } } ) ; let args = { cancel : false , foreignKeyData : { } , requestType : 'add' , data : this . previousData , type : events . actionBegin , index : index , rowData : this . previousData } ; gObj . trigger ( events . actionBegin , args ) ; if ( args . cancel ) { return ; } gObj . isEdit = true ; if ( gObj . editSettings . mode !== 'Dialog' ) { gObj . clearSelection ( ) ; } this . renderer . addNew ( args ) ; gObj . editModule . applyFormValidation ( ) ; args . type = events . actionComplete ; args . row = gObj . element . querySelector ( '.e-addedrow' ) ; gObj . trigger ( events . actionComplete , args ) ; this . args = args as EditArgs ; } protected deleteRecord ( fieldname ? , data ? ) { this . editRowIndex = this . parent . selectedRowIndex ; if ( data ) { data = ( data instanceof Array ) ? data : [ data ] ; let gObj = this . parent ; let index = 0 ; let dataLen = Object . keys ( data ) . length ; fieldname = fieldname || this . parent . getPrimaryKeyFieldNames ( ) [ 0 ] ; for ( let i = 0 ; i < dataLen ; i ++ ) { let tmpRecord ; let contained = gObj . currentViewData . some ( ( record ) => { tmpRecord = record ; return data [ i ] === getObject ( fieldname , record ) || data [ i ] === record ; } ) ; data [ i ] = contained ? tmpRecord : { [ fieldname ] : data [ i ] } ; } } this . parent . notify ( events . modelChanged , { requestType : 'delete' , type : events . actionBegin , foreignKeyData : { } , data : data ? data : this . parent . getSelectedRecords ( ) , tr : this . parent . getSelectedRows ( ) , cancel : false } ) ; } private stopEditStatus ( ) { let gObj = this . parent ; let elem = gObj . element . querySelector ( '.e-addedrow' ) ; let mElem ; let editMElem ; if ( gObj . getFrozenColumns ( ) ) { mElem = gObj . element . querySelectorAll ( '.e-addedrow' ) [ 1 ] ; editMElem = gObj . element . querySelectorAll ( '.e-editedrow' ) [ 1 ] ; if ( mElem ) { remove ( mElem ) ; } if ( editMElem ) { editMElem . classList . remove ( 'e-editedrow' ) ; } } if ( elem ) { remove ( elem ) ; } elem = gObj . element . querySelector ( '.e-editedrow' ) ; if ( elem ) { elem . classList . remove ( 'e-editedrow' ) ; } } hidden public addEventListener ( ) { if ( this . parent . isDestroyed ) { return ; } this . parent . on ( events . crudAction , this . editHandler , this ) ; this . parent . on ( events . doubleTap , this . dblClickHandler , this ) ; this . parent . on ( events . click , this . clickHandler , this ) ; this . parent . on ( events . recordAdded , this . requestSuccess , this ) ; this . parent . on ( events . dblclick , this . dblClickHandler , this ) ; this . parent . on ( events . deleteComplete , this . editComplete , this ) ; this . parent . on ( events . saveComplete , this . editComplete , this ) ; } hidden public removeEventListener ( ) { if ( this . parent . isDestroyed ) { return ; } this . parent . off ( events . crudAction , this . editHandler ) ; this . parent . off ( events . doubleTap , this . dblClickHandler ) ; this . parent . off ( events . click , this . clickHandler ) ; this . parent . off ( events . recordAdded , this . requestSuccess ) ; this . parent . off ( events . dblclick , this . dblClickHandler ) ; this . parent . off ( events . deleteComplete , this . editComplete ) ; this . parent . off ( events . saveComplete , this . editComplete ) ; } hidden public destroy ( ) { this . removeEventListener ( ) ; this . renderer . destroy ( ) ; } } interface EditArgs { data ? : Object ; requestType ? : string ; previousData ? : Object ; selectedRow ? : Number ; type ? : string ; promise ? : Promise < Object > ; }