refactor(common): use transform functions in NgOptimizedImage inputs (#50580)

This commit refactors the code of NgOptimizedImage directive to switch from getter/setter approach to convers inputs to use the `transform` function instead.

PR Close #50580
This commit is contained in:
Andrew Kushnir 2023-06-05 18:55:41 -07:00 committed by Pawel Kozlowski
parent 307f8eee2c
commit cefa3de3de
3 changed files with 36 additions and 82 deletions

View file

@ -599,20 +599,24 @@ export abstract class NgLocalization {
// @public
export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
set disableOptimizedSrcset(value: string | boolean | undefined);
// (undocumented)
get disableOptimizedSrcset(): boolean;
set fill(value: string | boolean | undefined);
// (undocumented)
get fill(): boolean;
set height(value: string | number | undefined);
// (undocumented)
get height(): number | undefined;
disableOptimizedSrcset: boolean;
fill: boolean;
height: number | undefined;
loaderParams?: {
[key: string]: any;
};
loading?: 'lazy' | 'eager' | 'auto';
// (undocumented)
static ngAcceptInputType_disableOptimizedSrcset: unknown;
// (undocumented)
static ngAcceptInputType_fill: unknown;
// (undocumented)
static ngAcceptInputType_height: unknown;
// (undocumented)
static ngAcceptInputType_priority: unknown;
// (undocumented)
static ngAcceptInputType_width: unknown;
// (undocumented)
ngOnChanges(changes: SimpleChanges): void;
// (undocumented)
ngOnDestroy(): void;
@ -620,15 +624,11 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
ngOnInit(): void;
ngSrc: string;
ngSrcset: string;
set priority(value: string | boolean | undefined);
// (undocumented)
get priority(): boolean;
priority: boolean;
sizes?: string;
set width(value: string | number | undefined);
width: number | undefined;
// (undocumented)
get width(): number | undefined;
// (undocumented)
static ɵdir: i0.ɵɵDirectiveDeclaration<NgOptimizedImage, "img[ngSrc]", never, { "ngSrc": { "alias": "ngSrc"; "required": false; }; "ngSrcset": { "alias": "ngSrcset"; "required": false; }; "sizes": { "alias": "sizes"; "required": false; }; "width": { "alias": "width"; "required": false; }; "height": { "alias": "height"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "priority": { "alias": "priority"; "required": false; }; "loaderParams": { "alias": "loaderParams"; "required": false; }; "disableOptimizedSrcset": { "alias": "disableOptimizedSrcset"; "required": false; }; "fill": { "alias": "fill"; "required": false; }; "src": { "alias": "src"; "required": false; }; "srcset": { "alias": "srcset"; "required": false; }; }, {}, never, never, true, never, false>;
static ɵdir: i0.ɵɵDirectiveDeclaration<NgOptimizedImage, "img[ngSrc]", never, { "ngSrc": { "alias": "ngSrc"; "required": true; }; "ngSrcset": { "alias": "ngSrcset"; "required": false; }; "sizes": { "alias": "sizes"; "required": false; }; "width": { "alias": "width"; "required": false; }; "height": { "alias": "height"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "priority": { "alias": "priority"; "required": false; }; "loaderParams": { "alias": "loaderParams"; "required": false; }; "disableOptimizedSrcset": { "alias": "disableOptimizedSrcset"; "required": false; }; "fill": { "alias": "fill"; "required": false; }; "src": { "alias": "src"; "required": false; }; "srcset": { "alias": "srcset"; "required": false; }; }, {}, never, never, true, never, false>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<NgOptimizedImage, never>;
}

View file

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Directive, ElementRef, inject, InjectionToken, Injector, Input, NgZone, OnChanges, OnDestroy, OnInit, PLATFORM_ID, Renderer2, SimpleChanges, ɵformatRuntimeError as formatRuntimeError, ɵRuntimeError as RuntimeError} from '@angular/core';
import {booleanAttribute, Directive, ElementRef, inject, InjectionToken, Injector, Input, NgZone, numberAttribute, OnChanges, OnDestroy, OnInit, PLATFORM_ID, Renderer2, SimpleChanges, ɵformatRuntimeError as formatRuntimeError, ɵRuntimeError as RuntimeError} from '@angular/core';
import {RuntimeErrorCode} from '../../errors';
import {isPlatformServer} from '../../platform_id';
@ -247,7 +247,7 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
* Image name will be processed by the image loader and the final URL will be applied as the `src`
* property of the image.
*/
@Input() ngSrc!: string;
@Input({required: true}) ngSrc!: string;
/**
* A comma separated list of width or density descriptors.
@ -272,30 +272,14 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
* For responsive images: the intrinsic width of the image in pixels.
* For fixed size images: the desired rendered width of the image in pixels.
*/
@Input()
set width(value: string|number|undefined) {
ngDevMode && assertGreaterThanZero(this, value, 'width');
this._width = inputToInteger(value);
}
get width(): number|undefined {
return this._width;
}
private _width?: number;
@Input({transform: numberAttribute}) width: number|undefined;
/**
* For responsive images: the intrinsic height of the image in pixels.
* For fixed size images: the desired rendered height of the image in pixels.* The intrinsic
* height of the image in pixels.
*/
@Input()
set height(value: string|number|undefined) {
ngDevMode && assertGreaterThanZero(this, value, 'height');
this._height = inputToInteger(value);
}
get height(): number|undefined {
return this._height;
}
private _height?: number;
@Input({transform: numberAttribute}) height: number|undefined;
/**
* The desired loading behavior (lazy, eager, or auto).
@ -308,14 +292,7 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
/**
* Indicates whether this image should have a high priority.
*/
@Input()
set priority(value: string|boolean|undefined) {
this._priority = inputToBoolean(value);
}
get priority(): boolean {
return this._priority;
}
private _priority = false;
@Input({transform: booleanAttribute}) priority = false;
/**
* Data to pass through to custom loaders.
@ -325,14 +302,7 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
/**
* Disables automatic srcset generation for this image.
*/
@Input()
set disableOptimizedSrcset(value: string|boolean|undefined) {
this._disableOptimizedSrcset = inputToBoolean(value);
}
get disableOptimizedSrcset(): boolean {
return this._disableOptimizedSrcset;
}
private _disableOptimizedSrcset = false;
@Input({transform: booleanAttribute}) disableOptimizedSrcset = false;
/**
* Sets the image to "fill mode", which eliminates the height/width requirement and adds
@ -340,14 +310,7 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
*
* @developerPreview
*/
@Input()
set fill(value: string|boolean|undefined) {
this._fill = inputToBoolean(value);
}
get fill(): boolean {
return this._fill;
}
private _fill = false;
@Input({transform: booleanAttribute}) fill = false;
/**
* Value of the `src` attribute if set on the host `<img>` element.
@ -381,6 +344,12 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
assertNonZeroRenderedHeight(this, this.imgElement, this.renderer);
} else {
assertNonEmptyWidthAndHeight(this);
if (this.height !== undefined) {
assertGreaterThanZero(this, this.height, 'height');
}
if (this.width !== undefined) {
assertGreaterThanZero(this, this.width, 'width');
}
// Only check for distorted images when not in fill mode, where
// images may be intentionally stretched, cropped or letterboxed.
assertNoImageDistortion(this, this.imgElement, this.renderer);
@ -548,7 +517,7 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
}
private shouldGenerateAutomaticSrcset(): boolean {
return !this._disableOptimizedSrcset && !this.srcset && this.imageLoader !== noopImageLoader &&
return !this.disableOptimizedSrcset && !this.srcset && this.imageLoader !== noopImageLoader &&
!(this.width! > FIXED_SRCSET_WIDTH_LIMIT || this.height! > FIXED_SRCSET_HEIGHT_LIMIT);
}
@ -568,20 +537,6 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {
/***** Helpers *****/
/**
* Convert input value to integer.
*/
function inputToInteger(value: string|number|undefined): number|undefined {
return typeof value === 'string' ? parseInt(value, 10) : value;
}
/**
* Convert input value to boolean.
*/
function inputToBoolean(value: unknown): boolean {
return value != null && `${value}` !== 'false';
}
/**
* Sorts provided config breakpoints and uses defaults.
*/
@ -778,9 +733,8 @@ function assertGreaterThanZero(dir: NgOptimizedImage, inputValue: unknown, input
if (!validNumber && !validString) {
throw new RuntimeError(
RuntimeErrorCode.INVALID_INPUT,
`${imgDirectiveDetails(dir.ngSrc)} \`${inputName}\` has an invalid value ` +
`(\`${inputValue}\`). To fix this, provide \`${inputName}\` ` +
`as a number greater than 0.`);
`${imgDirectiveDetails(dir.ngSrc)} \`${inputName}\` has an invalid value. ` +
`To fix this, provide \`${inputName}\` as a number greater than 0.`);
}
}

View file

@ -377,7 +377,7 @@ describe('Image directive', () => {
.toThrowError(
'NG02952: The NgOptimizedImage directive (activated on an <img> ' +
'element with the `ngSrc="img.png"`) has detected that `width` ' +
'has an invalid value (`0`). To fix this, provide `width` as ' +
'has an invalid value. To fix this, provide `width` as ' +
'a number greater than 0.');
});
@ -392,7 +392,7 @@ describe('Image directive', () => {
.toThrowError(
'NG02952: The NgOptimizedImage directive (activated on an <img> ' +
'element with the `ngSrc="img.png"`) has detected that `width` ' +
'has an invalid value (`10px`). To fix this, provide `width` ' +
'has an invalid value. To fix this, provide `width` ' +
'as a number greater than 0.');
});
@ -424,7 +424,7 @@ describe('Image directive', () => {
.toThrowError(
'NG02952: The NgOptimizedImage directive (activated on an <img> ' +
'element with the `ngSrc="img.png"`) has detected that `height` ' +
'has an invalid value (`0`). To fix this, provide `height` as a number ' +
'has an invalid value. To fix this, provide `height` as a number ' +
'greater than 0.');
});
@ -439,7 +439,7 @@ describe('Image directive', () => {
.toThrowError(
'NG02952: The NgOptimizedImage directive (activated on an <img> element ' +
'with the `ngSrc="img.png"`) has detected that `height` has an invalid ' +
'value (`10%`). To fix this, provide `height` as a number greater than 0.');
'value. To fix this, provide `height` as a number greater than 0.');
});
it('should throw if `ngSrc` value is not provided', () => {