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
This commit is contained in:
Kara Erickson 2022-08-10 17:11:59 -07:00 committed by Pawel Kozlowski
parent 45cc85f3b8
commit d71dfe931f
2 changed files with 18 additions and 0 deletions

View file

@ -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

View file

@ -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 = '<img rawSrc="path/img.png" [width]="width" [height]="height">';
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();