33 Component ,
44 ElementRef ,
55 EventEmitter ,
6- HostListener ,
76 Inject ,
87 Input ,
98 OnChanges ,
@@ -54,6 +53,12 @@ import { UnsubscribeComponent } from '../../../utils/unsubscribe/unsubscribe.com
5453import { DOCUMENT } from '@angular/common' ;
5554import { WidgetComponent } from '../../../widget/widget.component' ;
5655import { DatePipe } from '../../../../pipes/date/date.pipe' ;
56+ import { ResizeObservable } from '../../../../utils/rxjs/resize-observable.util' ;
57+
58+ /** Minimum column width */
59+ const MIN_COLUMN_WIDTH = 100 ;
60+ /** Maximum column width */
61+ const MAX_COLUMN_WIDTH = 250 ;
5762
5863/**
5964 * Test if an element match a css selector
@@ -283,14 +288,6 @@ export class GridComponent
283288 } ;
284289 }
285290
286- /**
287- * Listen to window resize event in order to trigger the column automatic width update
288- */
289- @HostListener ( 'window:resize' , [ '$event' ] )
290- onWindowResize ( ) {
291- this . setColumnsWidth ( ) ;
292- }
293-
294291 /**
295292 * Constructor of the grid component
296293 *
@@ -304,6 +301,7 @@ export class GridComponent
304301 * @param dashboardService Dashboard service
305302 * @param translate The translate service
306303 * @param snackBar The snackbar service
304+ * @param el Ref to html element
307305 * @param document document
308306 */
309307 constructor (
@@ -317,6 +315,7 @@ export class GridComponent
317315 private dashboardService : DashboardService ,
318316 private translate : TranslateService ,
319317 private snackBar : SnackbarService ,
318+ private el : ElementRef ,
320319 @Inject ( DOCUMENT ) private document : Document
321320 ) {
322321 super ( ) ;
@@ -373,6 +372,9 @@ export class GridComponent
373372 500
374373 ) ;
375374 } ) ;
375+ new ResizeObservable ( this . gridRef . nativeElement )
376+ . pipe ( debounceTime ( 100 ) , takeUntil ( this . destroy$ ) )
377+ . subscribe ( ( ) => this . setColumnsWidth ( ) ) ;
376378 }
377379
378380 override ngOnDestroy ( ) : void {
@@ -752,7 +754,6 @@ export class GridComponent
752754 this . action . emit ( { action : 'cancel' } ) ;
753755 }
754756
755- // === EXPORT ===
756757 /**
757758 * Downloads file of record.
758759 *
@@ -789,7 +790,6 @@ export class GridComponent
789790 } ) ;
790791 }
791792
792- // === UTILITIES ===
793793 /**
794794 * Checks if element overflows
795795 *
@@ -912,7 +912,7 @@ export class GridComponent
912912 }
913913
914914 /**
915- * Calls layout format from utils.ts to get the formated fields
915+ * Calls layout format from utils.ts to get the formatted fields
916916 *
917917 * @param name Content of the field as a string
918918 * @param field Field data
@@ -978,14 +978,15 @@ export class GridComponent
978978 * Automatically set the width of each column
979979 */
980980 private setColumnsWidth ( ) {
981+ console . log ( this . layout ) ;
981982 const gridElement = this . gridRef . nativeElement ;
982983 const gridTotalWidth = gridElement . offsetWidth ;
983984
984985 // Stores the columns width percentage
985986 const activeColumns : { [ key : string ] : number } = { } ;
986987
987988 // Verify what kind of field is and deal with this logic
988- const typesFields : any = [ ] ;
989+ const typesFields : { field : string ; type : string ; title : string } [ ] = [ ] ;
989990 this . fields . forEach ( ( field : any ) => {
990991 typesFields . push ( {
991992 field : field . name ,
@@ -1017,34 +1018,23 @@ export class GridComponent
10171018 activeColumns [ type . field ] < data [ type . field ] . length ) ||
10181019 ( type . title && activeColumns [ type . field ] < type . title . length )
10191020 ) {
1020- let defaultLengthValue = type . title . length ;
1021+ const titleSize = type . title . length ;
1022+ let contentSize = 0 ;
10211023 switch ( type . type ) {
10221024 case 'time' :
10231025 case 'datetime-local' :
10241026 case 'datetime' :
10251027 case 'date' : {
1026- const contentDefaultValue = (
1027- this . datePipe . transform ( data [ type . field ] ) || ''
1028- ) . length ;
1029- if ( contentDefaultValue > defaultLengthValue ) {
1030- defaultLengthValue = contentDefaultValue ;
1031- }
1032- activeColumns [ type . field ] = defaultLengthValue ;
1028+ contentSize = ( this . datePipe . transform ( data [ type . field ] ) || '' )
1029+ . length ;
10331030 break ;
10341031 }
10351032 case 'file' : {
1036- if ( data [ type . field ] [ 0 ] ?. name ?. length > defaultLengthValue ) {
1037- defaultLengthValue = data [ type . field ] [ 0 ] ?. name . length ;
1038- }
1039- activeColumns [ type . field ] = defaultLengthValue ;
1033+ contentSize = data [ type . field ] [ 0 ] ?. name ?. length || 0 ;
10401034 break ;
10411035 }
10421036 case 'numeric' : {
1043- const contentDefaultValue = data [ type . field ] ?. toString ( ) ?. length ;
1044- if ( contentDefaultValue > defaultLengthValue ) {
1045- defaultLengthValue = contentDefaultValue ;
1046- }
1047- activeColumns [ type . field ] = defaultLengthValue ;
1037+ contentSize = data [ type . field ] ?. toString ( ) ?. length ;
10481038 break ;
10491039 }
10501040 case 'checkbox' :
@@ -1053,30 +1043,46 @@ export class GridComponent
10531043 ( data [ type . field ] || [ ] ) . forEach ( ( obj : any ) => {
10541044 checkboxLength += obj . length ;
10551045 } ) ;
1056- if ( checkboxLength > defaultLengthValue ) {
1057- defaultLengthValue = checkboxLength ;
1058- }
1059- activeColumns [ type . field ] = defaultLengthValue ;
1046+ contentSize = checkboxLength ;
10601047 break ;
10611048 }
10621049 case 'boolean' :
10631050 case 'color' : {
10641051 //min size
1065- activeColumns [ type . field ] = type . title ;
1052+ contentSize = 0 ;
10661053 break ;
10671054 }
10681055 default : {
1069- const contentDefaultValue = ( data [ type . field ] || '' ) . length ;
1070- if ( contentDefaultValue > defaultLengthValue ) {
1071- defaultLengthValue = contentDefaultValue ;
1072- }
1073- activeColumns [ type . field ] = defaultLengthValue ;
1056+ contentSize = ( data [ type . field ] || '' ) . length ;
10741057 }
10751058 }
1059+
1060+ activeColumns [ type . field ] = Math . max ( titleSize , contentSize ) ;
10761061 }
10771062 } ) ;
10781063 } ) ;
10791064
1065+ const avgPixelPerCol = gridTotalWidth / typesFields . length ;
1066+
1067+ // If there are too many columns, we can't do the calculations by percentage
1068+ // Instead, clamp the columns to the min and max width
1069+ if ( avgPixelPerCol < MIN_COLUMN_WIDTH * 1.1 ) {
1070+ this . columns . forEach ( ( column ) => {
1071+ const colWidth = activeColumns [ column . field ] ;
1072+ if ( colWidth ) {
1073+ column . width = Math . min (
1074+ Math . max ( colWidth * pixelWidthPerCharacter , MIN_COLUMN_WIDTH ) ,
1075+ MAX_COLUMN_WIDTH
1076+ ) ;
1077+ }
1078+
1079+ // Make sure that every column has a width set
1080+ if ( column . width <= 0 ) {
1081+ column . width = MIN_COLUMN_WIDTH ;
1082+ }
1083+ } ) ;
1084+ return ;
1085+ }
10801086 // Calculates the widest column in character number
10811087 const maxCharacterToDisplay = Math . floor (
10821088 maxPixelsPerColumn / pixelWidthPerCharacter
@@ -1119,27 +1125,29 @@ export class GridComponent
11191125 // Order the values from thinner to wider column element
11201126 arrayColumns . sort ( ( a , b ) => a . value - b . value ) ;
11211127
1122- const widestColumnIndex = arrayColumns . length - 1 ;
1123- // if the value of the smallest element is 4x times smaller than the widest one
1124- // or the total percentage did not reach 100% after all conversions
1125- // we adjust the overall percentages set for columns
1126- while (
1127- arrayColumns [ 0 ] . value < 0.25 * arrayColumns [ widestColumnIndex ] . value ||
1128- total_percentage < 100
1129- ) {
1130- // Add the percentage available
1131- if ( total_percentage < 100 ) {
1132- activeColumns [ arrayColumns [ 0 ] . key ] += 1 ;
1133- total_percentage += 1 ;
1134- arrayColumns [ 0 ] . value += 1 ;
1135- } else {
1136- // Remove percentage from the biggest and put in the smallest
1137- activeColumns [ arrayColumns [ 0 ] . key ] += 1 ;
1138- activeColumns [ arrayColumns [ widestColumnIndex ] . key ] -= 1 ;
1139- arrayColumns [ 0 ] . value += 1 ;
1140- arrayColumns [ widestColumnIndex ] . value -= 1 ;
1128+ if ( arrayColumns . length > 0 ) {
1129+ const widestColumnIndex = arrayColumns . length - 1 ;
1130+ // if the value of the smallest element is 4x times smaller than the widest one
1131+ // or the total percentage did not reach 100% after all conversions
1132+ // we adjust the overall percentages set for columns
1133+ while (
1134+ arrayColumns [ 0 ] . value < 0.25 * arrayColumns [ widestColumnIndex ] . value ||
1135+ total_percentage < 100
1136+ ) {
1137+ // Add the percentage available
1138+ if ( total_percentage < 100 ) {
1139+ activeColumns [ arrayColumns [ 0 ] . key ] += 1 ;
1140+ total_percentage += 1 ;
1141+ arrayColumns [ 0 ] . value += 1 ;
1142+ } else {
1143+ // Remove percentage from the biggest and put in the smallest
1144+ activeColumns [ arrayColumns [ 0 ] . key ] += 1 ;
1145+ activeColumns [ arrayColumns [ widestColumnIndex ] . key ] -= 1 ;
1146+ arrayColumns [ 0 ] . value += 1 ;
1147+ arrayColumns [ widestColumnIndex ] . value -= 1 ;
1148+ }
1149+ arrayColumns . sort ( ( a , b ) => a . value - b . value ) ;
11411150 }
1142- arrayColumns . sort ( ( a , b ) => a . value - b . value ) ;
11431151 }
11441152
11451153 // Finally, resize the columns
@@ -1157,6 +1165,10 @@ export class GridComponent
11571165 column . width = Math . floor ( ( min_percentage * gridTotalWidth ) / 100 ) ;
11581166 }
11591167 }
1168+ // Make sure that every column has a width set
1169+ if ( column . width <= 0 ) {
1170+ column . width = MIN_COLUMN_WIDTH ;
1171+ }
11601172 } ) ;
11611173 }
11621174}
0 commit comments