@@ -18,20 +18,34 @@ import {ColumnResize} from './column-resize';
1818 */
1919@Injectable ( )
2020export abstract class ResizeStrategy {
21+ protected abstract readonly columnResize : ColumnResize ;
22+
23+ /** Updates the width of the specified column. */
2124 abstract applyColumnSize (
2225 cssFriendlyColumnName : string ,
2326 columnHeader : HTMLElement ,
24- sizeInPx : number ) : void ;
27+ sizeInPx : number ,
28+ previousSizeInPx ?: number ) : void ;
2529
30+ /** Applies a minimum width to the specified column, updating its current width as needed. */
2631 abstract applyMinColumnSize (
2732 cssFriendlyColumnName : string ,
2833 columnHeader : HTMLElement ,
2934 minSizeInPx : number ) : void ;
3035
36+ /** Applies a maximum width to the specified column, updating its current width as needed. */
3137 abstract applyMaxColumnSize (
3238 cssFriendlyColumnName : string ,
3339 columnHeader : HTMLElement ,
3440 minSizeInPx : number ) : void ;
41+
42+ /** Adjusts the width of the table element by the specified delta. */
43+ protected updateTableWidth ( delta : number ) : void {
44+ const table = this . columnResize . elementRef . nativeElement ;
45+ const tableWidth = getElementWidth ( table ) ;
46+
47+ table . style . width = coerceCssPixelValue ( tableWidth + delta ) ;
48+ }
3549}
3650
3751/**
@@ -43,17 +57,31 @@ export abstract class ResizeStrategy {
4357 */
4458@Injectable ( )
4559export class TableLayoutFixedResizeStrategy extends ResizeStrategy {
46- applyColumnSize ( _ : string , columnHeader : HTMLElement , sizeInPx : number ) : void {
60+ constructor ( protected readonly columnResize : ColumnResize ) {
61+ super ( ) ;
62+ }
63+
64+ applyColumnSize ( _ : string , columnHeader : HTMLElement , sizeInPx : number ,
65+ previousSizeInPx ?: number ) : void {
66+ const delta = sizeInPx - ( previousSizeInPx ?? getElementWidth ( columnHeader ) ) ;
67+
4768 columnHeader . style . width = coerceCssPixelValue ( sizeInPx ) ;
69+
70+ this . updateTableWidth ( delta ) ;
4871 }
4972
5073 applyMinColumnSize ( _ : string , columnHeader : HTMLElement , sizeInPx : number ) : void {
51- columnHeader . style . minWidth = coerceCssPixelValue ( sizeInPx ) ;
74+ const currentWidth = getElementWidth ( columnHeader ) ;
75+ const newWidth = Math . max ( currentWidth , sizeInPx ) ;
76+
77+ this . applyColumnSize ( _ , columnHeader , newWidth , currentWidth ) ;
5278 }
5379
54- applyMaxColumnSize ( ) : void {
55- // Intentionally omitted as max-width causes strange rendering issues in Chrome.
56- // Max size will still apply when the user is resizing this column.
80+ applyMaxColumnSize ( _ : string , columnHeader : HTMLElement , sizeInPx : number ) : void {
81+ const currentWidth = getElementWidth ( columnHeader ) ;
82+ const newWidth = Math . min ( currentWidth , sizeInPx ) ;
83+
84+ this . applyColumnSize ( _ , columnHeader , newWidth , currentWidth ) ;
5785 }
5886}
5987
@@ -76,16 +104,23 @@ export class CdkFlexTableResizeStrategy extends ResizeStrategy implements OnDest
76104 protected readonly defaultMaxSize = Number . MAX_SAFE_INTEGER ;
77105
78106 constructor (
79- private readonly _columnResize : ColumnResize ,
107+ protected readonly columnResize : ColumnResize ,
80108 @Inject ( DOCUMENT ) document : any ) {
81109 super ( ) ;
82110 this . _document = document ;
83111 }
84112
85- applyColumnSize ( cssFriendlyColumnName : string , _ : HTMLElement , sizeInPx : number ) : void {
113+ applyColumnSize ( cssFriendlyColumnName : string , columnHeader : HTMLElement ,
114+ sizeInPx : number , previousSizeInPx ?: number ) : void {
115+ // Optimization: Check applied width first as we probably set it already before reading
116+ // offsetWidth which triggers layout.
117+ const delta = sizeInPx - ( previousSizeInPx ??
118+ ( this . _getAppliedWidth ( cssFriendlyColumnName ) || columnHeader . offsetWidth ) ) ;
119+
86120 const cssSize = coerceCssPixelValue ( sizeInPx ) ;
87121
88122 this . _applyProperty ( cssFriendlyColumnName , 'flex' , `0 0.01 ${ cssSize } ` ) ;
123+ this . updateTableWidth ( delta ) ;
89124 }
90125
91126 applyMinColumnSize ( cssFriendlyColumnName : string , _ : HTMLElement , sizeInPx : number ) : void {
@@ -106,14 +141,23 @@ export class CdkFlexTableResizeStrategy extends ResizeStrategy implements OnDest
106141 return `cdk-column-${ cssFriendlyColumnName } ` ;
107142 }
108143
109- ngOnDestroy ( ) {
144+ ngOnDestroy ( ) : void {
110145 // TODO: Use remove() once we're off IE11.
111146 if ( this . _styleElement && this . _styleElement . parentNode ) {
112147 this . _styleElement . parentNode . removeChild ( this . _styleElement ) ;
113148 this . _styleElement = undefined ;
114149 }
115150 }
116151
152+ private _getPropertyValue ( cssFriendlyColumnName : string , key : string ) : string | undefined {
153+ const properties = this . _getColumnPropertiesMap ( cssFriendlyColumnName ) ;
154+ return properties . get ( key ) ;
155+ }
156+
157+ private _getAppliedWidth ( cssFriendslyColumnName : string ) : number {
158+ return coercePixelsFromFlexValue ( this . _getPropertyValue ( cssFriendslyColumnName , 'flex' ) ) ;
159+ }
160+
117161 private _applyProperty (
118162 cssFriendlyColumnName : string ,
119163 key : string ,
@@ -166,7 +210,7 @@ export class CdkFlexTableResizeStrategy extends ResizeStrategy implements OnDest
166210 }
167211
168212 const columnClassName = this . getColumnCssClass ( cssFriendlyColumnName ) ;
169- const tableClassName = this . _columnResize . getUniqueCssClass ( ) ;
213+ const tableClassName = this . columnResize . getUniqueCssClass ( ) ;
170214
171215 const selector = `.${ tableClassName } .${ columnClassName } ` ;
172216 const body = propertyKeys . map ( key => `${ key } :${ properties . get ( key ) } ` ) . join ( ';' ) ;
@@ -175,6 +219,26 @@ export class CdkFlexTableResizeStrategy extends ResizeStrategy implements OnDest
175219 }
176220}
177221
222+ /** Converts CSS pixel values to numbers, eg "123px" to 123. Returns NaN for non pixel values. */
223+ function coercePixelsFromCssValue ( cssValue : string ) : number {
224+ return Number ( cssValue . match ( / ( \d + ) p x / ) ?. [ 1 ] ) ;
225+ }
226+
227+ /** Gets the style.width pixels on the specified element if present, otherwise its offsetWidth. */
228+ function getElementWidth ( element : HTMLElement ) {
229+ // Optimization: Check style.width first as we probably set it already before reading
230+ // offsetWidth which triggers layout.
231+ return coercePixelsFromCssValue ( element . style . width ) || element . offsetWidth ;
232+ }
233+
234+ /**
235+ * Converts CSS flex values as set in CdkFlexTableResizeStrategy to numbers,
236+ * eg "0 0.01 123px" to 123.
237+ */
238+ function coercePixelsFromFlexValue ( flexValue : string | undefined ) : number {
239+ return Number ( flexValue ?. match ( / 0 0 \. 0 1 ( \d + ) p x / ) ?. [ 1 ] ) ;
240+ }
241+
178242export const TABLE_LAYOUT_FIXED_RESIZE_STRATEGY_PROVIDER : Provider = {
179243 provide : ResizeStrategy ,
180244 useClass : TableLayoutFixedResizeStrategy ,
0 commit comments