Skip to content

Commit

Permalink
fix(core): Updates error to use RuntimeError code
Browse files Browse the repository at this point in the history
This updates the iterable differ error to use more up-to-date error
codes.
  • Loading branch information
thePunderWoman committed Jun 27, 2022
1 parent 21cce3a commit 3a72e96
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 7 deletions.
16 changes: 16 additions & 0 deletions aio/content/errors/NG2200.md
@@ -0,0 +1,16 @@
@name Missing Iterable Differ
@category runtime
@shortDescription Cannot find a differ for object in ngFor

@description
`NgFor` could not find an iterable differ for the value passed in. Make sure it's an iterable, like an `Array`.

@debugging
When using ngFor in a template, you must use some type of Iterable, like `Array`, `Set`, `Map`, etc.
If you're trying to iterate over the keys in an object, you should look at the [KeyValue pipe](/api/common/KeyValuePipe) instead.

<!-- links -->

<!-- external links -->

<!-- end links -->
2 changes: 2 additions & 0 deletions goldens/public-api/common/errors.md
Expand Up @@ -9,6 +9,8 @@ export const enum RuntimeErrorCode {
// (undocumented)
INVALID_PIPE_ARGUMENT = 2100,
// (undocumented)
NG_FOR_MISSING_DIFFER = 2200,
// (undocumented)
PARENT_NG_SWITCH_NOT_FOUND = 2000
}

Expand Down
17 changes: 12 additions & 5 deletions packages/common/src/directives/ng_for_of.ts
Expand Up @@ -6,7 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Directive, DoCheck, EmbeddedViewRef, Input, IterableChangeRecord, IterableChanges, IterableDiffer, IterableDiffers, NgIterable, TemplateRef, TrackByFunction, ViewContainerRef} from '@angular/core';
import {Directive, DoCheck, EmbeddedViewRef, Input, IterableChangeRecord, IterableChanges, IterableDiffer, IterableDiffers, NgIterable, TemplateRef, TrackByFunction, ViewContainerRef, ɵRuntimeError as RuntimeError} from '@angular/core';

import {RuntimeErrorCode} from '../errors';

const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;

/**
* @publicApi
Expand Down Expand Up @@ -160,7 +164,7 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
*/
@Input()
set ngForTrackBy(fn: TrackByFunction<T>) {
if ((typeof ngDevMode === 'undefined' || ngDevMode) && fn != null && typeof fn !== 'function') {
if (NG_DEV_MODE && fn != null && typeof fn !== 'function') {
// TODO(vicb): use a log service once there is a public one available
if (<any>console && <any>console.warn) {
console.warn(
Expand Down Expand Up @@ -209,14 +213,17 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
// React on ngForOf changes only once all inputs have been initialized
const value = this._ngForOf;
if (!this._differ && value) {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
if (NG_DEV_MODE) {
try {
// CAUTION: this logic is duplicated for production mode below, as the try-catch
// is only present in development builds.
this._differ = this._differs.find(value).create(this.ngForTrackBy);
} catch {
throw new Error(`Cannot find a differ supporting object '${value}' of type '${
getTypeName(value)}'. NgFor only supports binding to Iterables such as Arrays.`);
throw new RuntimeError(
RuntimeErrorCode.NG_FOR_MISSING_DIFFER,
`Cannot find a differ supporting object '${value}' of type '${
getTypeName(
value)}'. NgFor only supports binding to Iterables, such as Arrays. Did you mean to use the keyvalue pipe?`);
}
} else {
// CAUTION: this logic is duplicated for development mode above, as the try-catch
Expand Down
4 changes: 3 additions & 1 deletion packages/common/src/errors.ts
Expand Up @@ -14,5 +14,7 @@ export const enum RuntimeErrorCode {
// NgSwitch errors
PARENT_NG_SWITCH_NOT_FOUND = 2000,
// Pipe errors
INVALID_PIPE_ARGUMENT = 2100
INVALID_PIPE_ARGUMENT = 2100,
// NgForOf errors
NG_FOR_MISSING_DIFFER = 2200,
}
2 changes: 1 addition & 1 deletion packages/common/test/directives/ng_for_spec.ts
Expand Up @@ -120,7 +120,7 @@ let thisArg: any;
getComponent().items = <any>'whaaa';
expect(() => fixture.detectChanges())
.toThrowError(
/Cannot find a differ supporting object 'whaaa' of type 'string'. NgFor only supports binding to Iterables such as Arrays/);
/NG02200: Cannot find a differ supporting object 'whaaa' of type 'string'. NgFor only supports binding to Iterables, such as Arrays. Did you mean to use the keyvalue pipe?/);
}));

it('should throw on ref changing to string', waitForAsync(() => {
Expand Down

0 comments on commit 3a72e96

Please sign in to comment.