import { L10n } from '@syncfusion/ej2-base' ; import { isNullOrUndefined , extend } from '@syncfusion/ej2-base' ; import { Column } from '../models/column' ; import { Cell } from '../models/cell' ; import { ICellRenderer , IValueFormatter , ICellFormatter , IGrid , ICell } from '../base/interface' ; import { doesImplementInterface , setStyleAndAttributes , appendChildren } from '../base/util' ; import { ServiceLocator } from '../services/service-locator' ; import { createCheckBox } from '@syncfusion/ej2-buttons' ; import { foreignKeyData } from '../base/constant' ; hidden export class CellRenderer implements ICellRenderer < Column > { public element : HTMLElement ; private rowChkBox : Element ; protected localizer : L10n ; protected formatter : IValueFormatter ; protected parent : IGrid ; constructor ( parent , locator ? ) { this . localizer = locator . getService < L10n > ( 'localization' ) ; this . formatter = locator . getService < IValueFormatter > ( 'valueFormatter' ) ; this . parent = parent ; this . element = this . parent . createElement ( 'TD' , { className : 'e-rowcell' , attrs : { role : 'gridcell' , tabindex : '-1' } } ) ; this . rowChkBox = this . parent . createElement ( 'input' , { className : 'e-checkselect' , attrs : { 'type' : 'checkbox' } } ) ; } returns public getGui ( ) { return '' ; } param { Column } column param { Object } value param { Object } data public format ( column , value , data ? ) { if ( ! isNullOrUndefined ( column . format ) ) { value = this . formatter . toView ( value as number | Date , column . getFormatter ( ) ) ; } return isNullOrUndefined ( value ) ? '' : value . toString ( ) ; } public evaluate ( node , cell , data , attributes ? , fData ? ) { let result ; if ( cell . column . template ) { let literals = [ 'index' ] ; let dummyData = extend ( { } , data , { [ foreignKeyData ] : fData } ) ; result = cell . column . getColumnTemplate ( ) ( extend ( { 'index' : attributes [ literals [ 0 ] ] } , dummyData ) , this . parent , 'template' ) ; appendChildren ( node , result ) ; result = null ; node . setAttribute ( 'aria-label' , ( < HTMLElement > node ) . innerText + ' is template cell' + ' column header ' + cell . column . headerText ) ; return false ; } return true ; } param { Column } column param { Object } value param { Object } data public invokeFormatter ( column , value , data ) { if ( ! isNullOrUndefined ( column . formatter ) ) { if ( doesImplementInterface ( column . formatter , 'getValue' ) ) { let formatter = < { new ( ) : ICellFormatter ; } > column . formatter ; value = new formatter ( ) . getValue ( column , data ) ; } else if ( typeof column . formatter === 'function' ) { value = ( column . formatter as Function ) ( column , data ) ; } else { value = ( column . formatter as ICellFormatter ) . getValue ( column , data ) ; } } return value ; } param { Column } column param { Object } data param { { [ x : string ] : Object } } attributes param { Element } public render ( cell , data , attributes ? ) { return this . refreshCell ( cell , data , attributes ) ; } param { Column } column param { Object } data param { { [ x : string ] : Object } } attributes param { Element } public refreshTD ( td , cell , data , attributes ? ) { let node = this . refreshCell ( cell , data , attributes ) ; td . innerHTML = '' ; let elements = [ ] . slice . call ( node . childNodes ) ; for ( let elem of elements ) { td . appendChild ( elem ) ; } } private refreshCell ( cell , data , attributes ? ) { let node = this . element . cloneNode ( ) as Element ; let column = cell . column ; let fData ; if ( cell . isForeignKey ) { fData = cell . foreignKeyData [ 0 ] || { [ column . foreignKeyValue ] : column . format ? null : '' } ; } let innerHtml = < string > this . getGui ( ) ; let value = cell . isForeignKey ? this . getValue ( column . foreignKeyValue , fData , column ) : this . getValue ( column . field , data , column ) ; if ( ( column . type === 'date' || column . type === 'datetime' ) && ! isNullOrUndefined ( value ) ) { value = new Date ( value as string ) ; } value = this . format ( column , value , data ) ; innerHtml = value . toString ( ) ; if ( column . type === 'boolean' && ! column . displayAsCheckBox ) { let localeStr = ( value !== 'true' && value !== 'false' ) ? null : value === 'true' ? 'True' : 'False' ; innerHtml = localeStr ? this . localizer . getConstant ( localeStr ) : innerHtml ; } let fromFormatter = this . invokeFormatter ( column , value , data ) ; innerHtml = ! isNullOrUndefined ( column . formatter ) ? isNullOrUndefined ( fromFormatter ) ? '' : fromFormatter . toString ( ) : innerHtml ; node . setAttribute ( 'aria-label' , ( innerHtml === '' ? 'empty' : innerHtml ) + ' column header ' + cell . column . headerText ) ; if ( ! isNullOrUndefined ( cell . column . headerText ) ) { node . setAttribute ( 'aria-label' , innerHtml + ' column header ' + cell . column . headerText ) ; } if ( this . evaluate ( node , cell , data , attributes , fData ) && column . type !== 'checkbox' ) { this . appendHtml ( node , innerHtml , column . getDomSetter ? column . getDomSetter ( ) : 'innerHTML' ) ; } else if ( column . type === 'checkbox' ) { node . classList . add ( 'e-gridchkbox' ) ; node . setAttribute ( 'aria-label' , 'checkbox' ) ; if ( this . parent . selectionSettings . persistSelection ) { value = value === 'true' ; } else { value = false ; } let checkWrap = createCheckBox ( this . parent . createElement , false , { checked : value as boolean , label : ' ' } ) ; checkWrap . insertBefore ( this . rowChkBox . cloneNode ( ) , checkWrap . firstChild ) ; node . appendChild ( checkWrap ) ; } if ( this . parent . checkAllRows === 'Check' && this . parent . enableVirtualization ) { cell . isSelected = true ; } this . setAttributes ( < HTMLElement > node , cell , attributes ) ; if ( column . type === 'boolean' && column . displayAsCheckBox ) { let checked = isNaN ( parseInt ( value . toString ( ) , 10 ) ) ? value === 'true' : parseInt ( value . toString ( ) , 10 ) > 0 ; let checkWrap = createCheckBox ( this . parent . createElement , false , { checked : checked , label : ' ' } ) ; node . innerHTML = '' ; checkWrap . classList . add ( 'e-checkbox-disabled' ) ; node . appendChild ( checkWrap ) ; node . setAttribute ( 'aria-label' , checked + ' column header ' + cell . column . headerText ) ; } return node ; } param { Element } node param { string | Element } innerHtml returns public appendHtml ( node , innerHtml , property = 'innerHTML' ) { node [ property ] = innerHtml as string ; return node ; } hidden public setAttributes ( node , cell , attributes ? ) { let column = cell . column ; this . buildAttributeFromCell ( node , cell , column . type === 'checkbox' ) ; setStyleAndAttributes ( node , attributes ) ; setStyleAndAttributes ( node , cell . attributes ) ; if ( column . customAttributes ) { setStyleAndAttributes ( node , column . customAttributes ) ; } if ( column . textAlign ) { node . style . textAlign = column . textAlign ; } if ( column . clipMode === 'Clip' ) { node . classList . add ( 'e-gridclip' ) ; } else if ( column . clipMode === 'EllipsisWithTooltip' ) { node . classList . add ( 'e-ellipsistooltip' ) ; } } public buildAttributeFromCell < Column > ( node , cell , isCheckBoxType ? ) { let attr = { } ; let prop = { 'colindex' : 'aria-colindex' } ; let classes = [ ] ; if ( cell . colSpan ) { attr . colSpan = cell . colSpan ; } if ( cell . rowSpan ) { attr . rowSpan = cell . rowSpan ; } if ( cell . isTemplate ) { classes . push ( 'e-templatecell' ) ; } if ( cell . isSelected ) { classes . push ( ... [ 'e-selectionbackground' , 'e-active' ] ) ; if ( isCheckBoxType ) { node . querySelector ( '.e-frame' ) . classList . add ( 'e-check' ) ; } } if ( ! isNullOrUndefined ( cell . index ) ) { attr [ prop . colindex ] = cell . index ; } if ( ! cell . visible ) { classes . push ( 'e-hide' ) ; } attr . class = classes ; setStyleAndAttributes ( node , attr ) ; } public getValue ( field , data , column ) { return ( column . valueAccessor as Function ) ( field , data , column ) ; } }