refactor(common): create an NgFor alias for NgForOf directive (#47309)

This commit adds a re-export of the `NgForOf` class as `NgFor` to improve the DX for cases when the directive is used as standalone. Developers can import `NgFor` class, which better matches the `ngFor` attribute used in a template.

PR Close #47309
This commit is contained in:
Andrew Kushnir 2022-08-31 10:51:05 -07:00 committed by Dylan Hunn
parent 7e0de5b8be
commit 710d1da4ed
7 changed files with 34 additions and 6 deletions

View file

@ -450,7 +450,7 @@ export class NgComponentOutlet implements OnChanges, OnDestroy {
}
// @public
export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCheck {
class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCheck {
constructor(_viewContainer: ViewContainerRef, _template: TemplateRef<NgForOfContext<T, U>>, _differs: IterableDiffers);
ngDoCheck(): void;
set ngForOf(ngForOf: U & NgIterable<T> | undefined | null);
@ -464,6 +464,8 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<NgForOf<any, any>, never>;
}
export { NgForOf as NgFor }
export { NgForOf }
// @public (undocumented)
export class NgForOfContext<T, U extends NgIterable<T> = NgIterable<T>> {

View file

@ -20,7 +20,7 @@ export {registerLocaleData} from './i18n/locale_data';
export {Plural, NumberFormatStyle, FormStyle, Time, TranslationWidth, FormatWidth, NumberSymbol, WeekDay, getNumberOfCurrencyDigits, getCurrencySymbol, getLocaleDayPeriods, getLocaleDayNames, getLocaleMonthNames, getLocaleId, getLocaleEraNames, getLocaleWeekEndRange, getLocaleFirstDayOfWeek, getLocaleDateFormat, getLocaleDateTimeFormat, getLocaleExtraDayPeriodRules, getLocaleExtraDayPeriods, getLocalePluralCase, getLocaleTimeFormat, getLocaleNumberSymbol, getLocaleNumberFormat, getLocaleCurrencyCode, getLocaleCurrencyName, getLocaleCurrencySymbol, getLocaleDirection} from './i18n/locale_data_api';
export {parseCookieValue as ɵparseCookieValue} from './cookie';
export {CommonModule} from './common_module';
export {NgClass, NgForOf, NgForOfContext, NgIf, NgIfContext, NgPlural, NgPluralCase, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet, NgComponentOutlet} from './directives/index';
export {NgClass, NgFor, NgForOf, NgForOfContext, NgIf, NgIfContext, NgPlural, NgPluralCase, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet, NgComponentOutlet} from './directives/index';
export {DOCUMENT} from './dom_tokens';
export {AsyncPipe, DatePipe, DATE_PIPE_DEFAULT_TIMEZONE, I18nPluralPipe, I18nSelectPipe, JsonPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe, TitleCasePipe, KeyValuePipe, KeyValue} from './pipes/index';
export {PLATFORM_BROWSER_ID as ɵPLATFORM_BROWSER_ID, PLATFORM_SERVER_ID as ɵPLATFORM_SERVER_ID, PLATFORM_WORKER_APP_ID as ɵPLATFORM_WORKER_APP_ID, PLATFORM_WORKER_UI_ID as ɵPLATFORM_WORKER_UI_ID, isPlatformBrowser, isPlatformServer, isPlatformWorkerApp, isPlatformWorkerUi} from './platform_id';

View file

@ -7,9 +7,10 @@
*/
import {Provider} from '@angular/core';
import {NgClass} from './ng_class';
import {NgComponentOutlet} from './ng_component_outlet';
import {NgForOf, NgForOfContext} from './ng_for_of';
import {NgFor, NgForOf, NgForOfContext} from './ng_for_of';
import {NgIf, NgIfContext} from './ng_if';
import {NgPlural, NgPluralCase} from './ng_plural';
import {NgStyle} from './ng_style';
@ -19,6 +20,7 @@ import {NgTemplateOutlet} from './ng_template_outlet';
export {
NgClass,
NgComponentOutlet,
NgFor,
NgForOf,
NgForOfContext,
NgIf,

View file

@ -290,6 +290,11 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
}
}
// Also export the `NgForOf` class as `NgFor` to improve the DX for
// cases when the directive is used as standalone, so the class name
// matches the CSS selector (*ngFor).
export {NgForOf as NgFor};
function applyViewChange<T>(
view: EmbeddedViewRef<NgForOfContext<T>>, record: IterableChangeRecord<T>) {
view.context.$implicit = record.item;

View file

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CommonModule, NgForOf} from '@angular/common';
import {CommonModule, NgFor, NgForOf} from '@angular/common';
import {Component} from '@angular/core';
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
@ -408,6 +408,25 @@ let thisArg: any;
expect(fixture.nativeElement.textContent).toBe('1|2|3|');
});
it('should be available as a standalone directive using an `NgFor` alias', () => {
@Component({
selector: 'test-component',
imports: [NgFor],
template: `
<ng-container *ngFor="let item of items">{{ item }}|</ng-container>
`,
standalone: true,
})
class TestComponent {
items = [1, 2, 3];
}
const fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
expect(fixture.nativeElement.textContent).toBe('1|2|3|');
});
});
}

View file

@ -24,7 +24,7 @@ import {TemplateCheckFactory, TemplateCheckWithVisitor, TemplateContext} from '.
* `CommonModule` is included, the `ngSwitch` would also be covered.
*/
export const KNOWN_CONTROL_FLOW_DIRECTIVES = new Map([
['ngIf', 'NgIf'], ['ngFor', 'NgForOf'], ['ngSwitchCase', 'NgSwitchCase'],
['ngIf', 'NgIf'], ['ngFor', 'NgFor'], ['ngSwitchCase', 'NgSwitchCase'],
['ngSwitchDefault', 'NgSwitchDefault']
]);

View file

@ -282,7 +282,7 @@ function getTemplateLocationDetails(lView: LView): string {
* that the `CommonModule` should also be included.
*/
export const KNOWN_CONTROL_FLOW_DIRECTIVES = new Map([
['ngIf', 'NgIf'], ['ngFor', 'NgForOf'], ['ngSwitchCase', 'NgSwitchCase'],
['ngIf', 'NgIf'], ['ngFor', 'NgFor'], ['ngSwitchCase', 'NgSwitchCase'],
['ngSwitchDefault', 'NgSwitchDefault']
]);
/**