From d71dfe931f71bff71e4e7af96aebd59f31cd4079 Mon Sep 17 00:00:00 2001 From: Kara Erickson Date: Wed, 10 Aug 2022 17:11:59 -0700 Subject: [PATCH] fix(common): set bound width and height onto host element (#47082) This commit fixes a bug in NgOptimizedImage where if you bound the width or height attribute (e.g. `[width]=width`), the attribute would only be reflected as "ng-reflect-x". The actual "width" or "height" attribute would not be set on the host element. This is a problem because the exact named attribute must be set on the element for the browser to detect it and use it to reserve space for the image (and thus prevent CLS). PR Close #47082 --- .../ng_optimized_image/ng_optimized_image.ts | 5 +++++ .../test/directives/ng_optimized_image_spec.ts | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/packages/common/src/directives/ng_optimized_image/ng_optimized_image.ts b/packages/common/src/directives/ng_optimized_image/ng_optimized_image.ts index b1a03205b2b88..73309102c3d0b 100644 --- a/packages/common/src/directives/ng_optimized_image/ng_optimized_image.ts +++ b/packages/common/src/directives/ng_optimized_image/ng_optimized_image.ts @@ -267,6 +267,11 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy { observer.registerImage(this.getRewrittenSrc(), this.rawSrc)); } } + // Must set width/height explicitly in case they are bound (in which case they will + // only be reflected and not found by the browser) + this.setHostAttribute('width', this.width!.toString()); + this.setHostAttribute('height', this.height!.toString()); + this.setHostAttribute('loading', this.getLoadingBehavior()); this.setHostAttribute('fetchpriority', this.getFetchPriority()); // The `src` and `srcset` attributes should be set last since other attributes diff --git a/packages/common/test/directives/ng_optimized_image_spec.ts b/packages/common/test/directives/ng_optimized_image_spec.ts index c8c40d87ed868..3a53f139ea365 100644 --- a/packages/common/test/directives/ng_optimized_image_spec.ts +++ b/packages/common/test/directives/ng_optimized_image_spec.ts @@ -68,6 +68,19 @@ describe('Image directive', () => { expect(_fetchpriorityAttrId).toBeLessThan(_srcAttrId); // was set after `src` }); + it('should always reflect the width/height attributes if bound', () => { + setupTestingModule(); + + const template = ''; + const fixture = createTestComponent(template); + fixture.detectChanges(); + + const nativeElement = fixture.nativeElement as HTMLElement; + const img = nativeElement.querySelector('img')!; + expect(img.getAttribute('width')).toBe('100'); + expect(img.getAttribute('height')).toBe('50'); + }); + describe('setup error handling', () => { it('should throw if both `src` and `rawSrc` are present', () => { setupTestingModule();