Skip to content

Commit

Permalink
refactor(common): use transform functions in NgOptimizedImage inputs
Browse files Browse the repository at this point in the history
This commit refactors the code of NgOptimizedImage directive to switch from getter/setter approach to convers inputs to use the `transform` function instead.
  • Loading branch information
AndrewKushnir committed Jun 12, 2023
1 parent a163d35 commit dffc8c7
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 82 deletions.
32 changes: 16 additions & 16 deletions goldens/public-api/common/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -599,36 +599,36 @@ 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;
// (undocumented)
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);
// (undocumented)
get width(): number | undefined;
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>;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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.
Expand All @@ -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).
Expand All @@ -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.
Expand All @@ -325,29 +302,15 @@ 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
* styles such that the image fills its containing element.
*
* @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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand All @@ -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.
*/
Expand Down Expand Up @@ -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.`);
}
}

Expand Down
8 changes: 4 additions & 4 deletions packages/common/test/directives/ng_optimized_image_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.');
});

Expand All @@ -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.');
});

Expand Down Expand Up @@ -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.');
});

Expand All @@ -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', () => {
Expand Down

0 comments on commit dffc8c7

Please sign in to comment.