Skip to content

Commit a7597dd

Browse files
AndrewKushnirdylhunn
authored andcommittedJun 28, 2022
feat(common): make the CommonModule directives standalone (#46469)
This commit updates the directives presents in the `CommonModule` and annotates them with the `standalone: true` flag. With that flag, the directives can now be imported individually, as well as imported via the `CommonModule`. PR Close #46469
1 parent ee39cf6 commit a7597dd

18 files changed

+229
-36
lines changed
 

‎goldens/public-api/common/index.md

+12-12
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export class CommonModule {
5555
// (undocumented)
5656
static ɵinj: i0.ɵɵInjectorDeclaration<CommonModule>;
5757
// (undocumented)
58-
static ɵmod: i0.ɵɵNgModuleDeclaration<CommonModule, [typeof i1.NgClass, typeof i2.NgComponentOutlet, typeof i3.NgForOf, typeof i4.NgIf, typeof i5.NgTemplateOutlet, typeof i6.NgStyle, typeof i7.NgSwitch, typeof i7.NgSwitchCase, typeof i7.NgSwitchDefault, typeof i8.NgPlural, typeof i8.NgPluralCase], [typeof i9.AsyncPipe, typeof i10.UpperCasePipe, typeof i10.LowerCasePipe, typeof i11.JsonPipe, typeof i12.SlicePipe, typeof i13.DecimalPipe, typeof i13.PercentPipe, typeof i10.TitleCasePipe, typeof i13.CurrencyPipe, typeof i14.DatePipe, typeof i15.I18nPluralPipe, typeof i16.I18nSelectPipe, typeof i17.KeyValuePipe], [typeof i1.NgClass, typeof i2.NgComponentOutlet, typeof i3.NgForOf, typeof i4.NgIf, typeof i5.NgTemplateOutlet, typeof i6.NgStyle, typeof i7.NgSwitch, typeof i7.NgSwitchCase, typeof i7.NgSwitchDefault, typeof i8.NgPlural, typeof i8.NgPluralCase, typeof i9.AsyncPipe, typeof i10.UpperCasePipe, typeof i10.LowerCasePipe, typeof i11.JsonPipe, typeof i12.SlicePipe, typeof i13.DecimalPipe, typeof i13.PercentPipe, typeof i10.TitleCasePipe, typeof i13.CurrencyPipe, typeof i14.DatePipe, typeof i15.I18nPluralPipe, typeof i16.I18nSelectPipe, typeof i17.KeyValuePipe]>;
58+
static ɵmod: i0.ɵɵNgModuleDeclaration<CommonModule, never, [typeof i1.NgClass, typeof i2.NgComponentOutlet, typeof i3.NgForOf, typeof i4.NgIf, typeof i5.NgTemplateOutlet, typeof i6.NgStyle, typeof i7.NgSwitch, typeof i7.NgSwitchCase, typeof i7.NgSwitchDefault, typeof i8.NgPlural, typeof i8.NgPluralCase, typeof i9.AsyncPipe, typeof i10.UpperCasePipe, typeof i10.LowerCasePipe, typeof i11.JsonPipe, typeof i12.SlicePipe, typeof i13.DecimalPipe, typeof i13.PercentPipe, typeof i10.TitleCasePipe, typeof i13.CurrencyPipe, typeof i14.DatePipe, typeof i15.I18nPluralPipe, typeof i16.I18nSelectPipe, typeof i17.KeyValuePipe], [typeof i1.NgClass, typeof i2.NgComponentOutlet, typeof i3.NgForOf, typeof i4.NgIf, typeof i5.NgTemplateOutlet, typeof i6.NgStyle, typeof i7.NgSwitch, typeof i7.NgSwitchCase, typeof i7.NgSwitchDefault, typeof i8.NgPlural, typeof i8.NgPluralCase, typeof i9.AsyncPipe, typeof i10.UpperCasePipe, typeof i10.LowerCasePipe, typeof i11.JsonPipe, typeof i12.SlicePipe, typeof i13.DecimalPipe, typeof i13.PercentPipe, typeof i10.TitleCasePipe, typeof i13.CurrencyPipe, typeof i14.DatePipe, typeof i15.I18nPluralPipe, typeof i16.I18nSelectPipe, typeof i17.KeyValuePipe]>;
5959
}
6060

6161
// @public
@@ -407,7 +407,7 @@ export class NgClass implements DoCheck {
407407
// (undocumented)
408408
ngDoCheck(): void;
409409
// (undocumented)
410-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgClass, "[ngClass]", never, { "klass": "class"; "ngClass": "ngClass"; }, {}, never, never, false>;
410+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgClass, "[ngClass]", never, { "klass": "class"; "ngClass": "ngClass"; }, {}, never, never, true>;
411411
// (undocumented)
412412
static ɵfac: i0.ɵɵFactoryDeclaration<NgClass, never>;
413413
}
@@ -430,7 +430,7 @@ export class NgComponentOutlet implements OnChanges, OnDestroy {
430430
// (undocumented)
431431
ngOnDestroy(): void;
432432
// (undocumented)
433-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgComponentOutlet, "[ngComponentOutlet]", never, { "ngComponentOutlet": "ngComponentOutlet"; "ngComponentOutletInjector": "ngComponentOutletInjector"; "ngComponentOutletContent": "ngComponentOutletContent"; "ngComponentOutletNgModule": "ngComponentOutletNgModule"; "ngComponentOutletNgModuleFactory": "ngComponentOutletNgModuleFactory"; }, {}, never, never, false>;
433+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgComponentOutlet, "[ngComponentOutlet]", never, { "ngComponentOutlet": "ngComponentOutlet"; "ngComponentOutletInjector": "ngComponentOutletInjector"; "ngComponentOutletContent": "ngComponentOutletContent"; "ngComponentOutletNgModule": "ngComponentOutletNgModule"; "ngComponentOutletNgModuleFactory": "ngComponentOutletNgModuleFactory"; }, {}, never, never, true>;
434434
// (undocumented)
435435
static ɵfac: i0.ɵɵFactoryDeclaration<NgComponentOutlet, never>;
436436
}
@@ -446,7 +446,7 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
446446
get ngForTrackBy(): TrackByFunction<T>;
447447
static ngTemplateContextGuard<T, U extends NgIterable<T>>(dir: NgForOf<T, U>, ctx: any): ctx is NgForOfContext<T, U>;
448448
// (undocumented)
449-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgForOf<any, any>, "[ngFor][ngForOf]", never, { "ngForOf": "ngForOf"; "ngForTrackBy": "ngForTrackBy"; "ngForTemplate": "ngForTemplate"; }, {}, never, never, false>;
449+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgForOf<any, any>, "[ngFor][ngForOf]", never, { "ngForOf": "ngForOf"; "ngForTrackBy": "ngForTrackBy"; "ngForTemplate": "ngForTemplate"; }, {}, never, never, true>;
450450
// (undocumented)
451451
static ɵfac: i0.ɵɵFactoryDeclaration<NgForOf<any, any>, never>;
452452
}
@@ -481,7 +481,7 @@ export class NgIf<T = unknown> {
481481
static ngTemplateContextGuard<T>(dir: NgIf<T>, ctx: any): ctx is NgIfContext<Exclude<T, false | 0 | '' | null | undefined>>;
482482
static ngTemplateGuard_ngIf: 'binding';
483483
// (undocumented)
484-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgIf<any>, "[ngIf]", never, { "ngIf": "ngIf"; "ngIfThen": "ngIfThen"; "ngIfElse": "ngIfElse"; }, {}, never, never, false>;
484+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgIf<any>, "[ngIf]", never, { "ngIf": "ngIf"; "ngIfThen": "ngIfThen"; "ngIfElse": "ngIfElse"; }, {}, never, never, true>;
485485
// (undocumented)
486486
static ɵfac: i0.ɵɵFactoryDeclaration<NgIf<any>, never>;
487487
}
@@ -525,7 +525,7 @@ export class NgPlural {
525525
// (undocumented)
526526
set ngPlural(value: number);
527527
// (undocumented)
528-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgPlural, "[ngPlural]", never, { "ngPlural": "ngPlural"; }, {}, never, never, false>;
528+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgPlural, "[ngPlural]", never, { "ngPlural": "ngPlural"; }, {}, never, never, true>;
529529
// (undocumented)
530530
static ɵfac: i0.ɵɵFactoryDeclaration<NgPlural, never>;
531531
}
@@ -536,7 +536,7 @@ export class NgPluralCase {
536536
// (undocumented)
537537
value: string;
538538
// (undocumented)
539-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgPluralCase, "[ngPluralCase]", never, {}, {}, never, never, false>;
539+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgPluralCase, "[ngPluralCase]", never, {}, {}, never, never, true>;
540540
// (undocumented)
541541
static ɵfac: i0.ɵɵFactoryDeclaration<NgPluralCase, [{ attribute: "ngPluralCase"; }, null, null, { host: true; }]>;
542542
}
@@ -551,7 +551,7 @@ export class NgStyle implements DoCheck {
551551
[klass: string]: any;
552552
} | null);
553553
// (undocumented)
554-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgStyle, "[ngStyle]", never, { "ngStyle": "ngStyle"; }, {}, never, never, false>;
554+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgStyle, "[ngStyle]", never, { "ngStyle": "ngStyle"; }, {}, never, never, true>;
555555
// (undocumented)
556556
static ɵfac: i0.ɵɵFactoryDeclaration<NgStyle, never>;
557557
}
@@ -561,7 +561,7 @@ export class NgSwitch {
561561
// (undocumented)
562562
set ngSwitch(newValue: any);
563563
// (undocumented)
564-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgSwitch, "[ngSwitch]", never, { "ngSwitch": "ngSwitch"; }, {}, never, never, false>;
564+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgSwitch, "[ngSwitch]", never, { "ngSwitch": "ngSwitch"; }, {}, never, never, true>;
565565
// (undocumented)
566566
static ɵfac: i0.ɵɵFactoryDeclaration<NgSwitch, never>;
567567
}
@@ -572,7 +572,7 @@ export class NgSwitchCase implements DoCheck {
572572
ngDoCheck(): void;
573573
ngSwitchCase: any;
574574
// (undocumented)
575-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgSwitchCase, "[ngSwitchCase]", never, { "ngSwitchCase": "ngSwitchCase"; }, {}, never, never, false>;
575+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgSwitchCase, "[ngSwitchCase]", never, { "ngSwitchCase": "ngSwitchCase"; }, {}, never, never, true>;
576576
// (undocumented)
577577
static ɵfac: i0.ɵɵFactoryDeclaration<NgSwitchCase, [null, null, { optional: true; host: true; }]>;
578578
}
@@ -581,7 +581,7 @@ export class NgSwitchCase implements DoCheck {
581581
export class NgSwitchDefault {
582582
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>, ngSwitch: NgSwitch);
583583
// (undocumented)
584-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgSwitchDefault, "[ngSwitchDefault]", never, {}, {}, never, never, false>;
584+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgSwitchDefault, "[ngSwitchDefault]", never, {}, {}, never, never, true>;
585585
// (undocumented)
586586
static ɵfac: i0.ɵɵFactoryDeclaration<NgSwitchDefault, [null, null, { optional: true; host: true; }]>;
587587
}
@@ -595,7 +595,7 @@ export class NgTemplateOutlet implements OnChanges {
595595
ngTemplateOutletContext: Object | null;
596596
ngTemplateOutletInjector: Injector | null;
597597
// (undocumented)
598-
static ɵdir: i0.ɵɵDirectiveDeclaration<NgTemplateOutlet, "[ngTemplateOutlet]", never, { "ngTemplateOutletContext": "ngTemplateOutletContext"; "ngTemplateOutlet": "ngTemplateOutlet"; "ngTemplateOutletInjector": "ngTemplateOutletInjector"; }, {}, never, never, false>;
598+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgTemplateOutlet, "[ngTemplateOutlet]", never, { "ngTemplateOutletContext": "ngTemplateOutletContext"; "ngTemplateOutlet": "ngTemplateOutlet"; "ngTemplateOutletInjector": "ngTemplateOutletInjector"; }, {}, never, never, true>;
599599
// (undocumented)
600600
static ɵfac: i0.ɵɵFactoryDeclaration<NgTemplateOutlet, never>;
601601
}

‎packages/common/src/common_module.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,10 @@ import {COMMON_PIPES} from './pipes/index';
2121
* Re-exported by `BrowserModule`, which is included automatically in the root
2222
* `AppModule` when you create a new app with the CLI `new` command.
2323
*
24-
* * The `providers` options configure the NgModule's injector to provide
25-
* localization dependencies to members.
26-
* * The `exports` options make the declared directives and pipes available for import
27-
* by other NgModules.
28-
*
2924
* @publicApi
3025
*/
3126
@NgModule({
32-
imports: [COMMON_PIPES],
33-
declarations: [COMMON_DIRECTIVES],
27+
imports: [COMMON_DIRECTIVES, COMMON_PIPES],
3428
exports: [COMMON_DIRECTIVES, COMMON_PIPES],
3529
})
3630
export class CommonModule {

‎packages/common/src/directives/ng_class.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ type NgClassSupportedTypes = string[]|Set<string>|{[klass: string]: any}|null|un
3737
*
3838
* @publicApi
3939
*/
40-
@Directive({selector: '[ngClass]'})
40+
@Directive({
41+
selector: '[ngClass]',
42+
standalone: true,
43+
})
4144
export class NgClass implements DoCheck {
4245
private _iterableDiffer: IterableDiffer<string>|null = null;
4346
private _keyValueDiffer: KeyValueDiffer<string, any>|null = null;

‎packages/common/src/directives/ng_component_outlet.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ import {ComponentRef, createNgModuleRef, Directive, Injector, Input, NgModuleFac
6868
* @publicApi
6969
* @ngModule CommonModule
7070
*/
71-
@Directive({selector: '[ngComponentOutlet]'})
71+
@Directive({
72+
selector: '[ngComponentOutlet]',
73+
standalone: true,
74+
})
7275
export class NgComponentOutlet implements OnChanges, OnDestroy {
7376
@Input() ngComponentOutlet: Type<any>|null = null;
7477

‎packages/common/src/directives/ng_for_of.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,10 @@ export class NgForOfContext<T, U extends NgIterable<T> = NgIterable<T>> {
133133
* @ngModule CommonModule
134134
* @publicApi
135135
*/
136-
@Directive({selector: '[ngFor][ngForOf]'})
136+
@Directive({
137+
selector: '[ngFor][ngForOf]',
138+
standalone: true,
139+
})
137140
export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCheck {
138141
/**
139142
* The value of the iterable expression, which can be used as a

‎packages/common/src/directives/ng_if.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,10 @@ import {Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef, ɵstri
148148
* @ngModule CommonModule
149149
* @publicApi
150150
*/
151-
@Directive({selector: '[ngIf]'})
151+
@Directive({
152+
selector: '[ngIf]',
153+
standalone: true,
154+
})
152155
export class NgIf<T = unknown> {
153156
private _context: NgIfContext<T> = new NgIfContext<T>();
154157
private _thenTemplateRef: TemplateRef<NgIfContext<T>>|null = null;

‎packages/common/src/directives/ng_plural.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ import {SwitchView} from './ng_switch';
4444
*
4545
* @publicApi
4646
*/
47-
@Directive({selector: '[ngPlural]'})
47+
@Directive({
48+
selector: '[ngPlural]',
49+
standalone: true,
50+
})
4851
export class NgPlural {
4952
// TODO(issue/24571): remove '!'.
5053
private _switchValue!: number;
@@ -104,7 +107,10 @@ export class NgPlural {
104107
*
105108
* @publicApi
106109
*/
107-
@Directive({selector: '[ngPluralCase]'})
110+
@Directive({
111+
selector: '[ngPluralCase]',
112+
standalone: true,
113+
})
108114
export class NgPluralCase {
109115
constructor(
110116
@Attribute('ngPluralCase') public value: string, template: TemplateRef<Object>,

‎packages/common/src/directives/ng_style.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ import {Directive, DoCheck, ElementRef, Input, KeyValueChanges, KeyValueDiffer,
4444
*
4545
* @publicApi
4646
*/
47-
@Directive({selector: '[ngStyle]'})
47+
@Directive({
48+
selector: '[ngStyle]',
49+
standalone: true,
50+
})
4851
export class NgStyle implements DoCheck {
4952
private _ngStyle: {[key: string]: string}|null = null;
5053
private _differ: KeyValueDiffer<string, string|number>|null = null;

‎packages/common/src/directives/ng_switch.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ export class SwitchView {
101101
* @see [Structural Directives](guide/structural-directives)
102102
*
103103
*/
104-
@Directive({selector: '[ngSwitch]'})
104+
@Directive({
105+
selector: '[ngSwitch]',
106+
standalone: true,
107+
})
105108
export class NgSwitch {
106109
// TODO(issue/24571): remove '!'.
107110
private _defaultViews!: SwitchView[];
@@ -189,7 +192,10 @@ export class NgSwitch {
189192
* @see `NgSwitchDefault`
190193
*
191194
*/
192-
@Directive({selector: '[ngSwitchCase]'})
195+
@Directive({
196+
selector: '[ngSwitchCase]',
197+
standalone: true,
198+
})
193199
export class NgSwitchCase implements DoCheck {
194200
private _view: SwitchView;
195201
/**
@@ -231,7 +237,10 @@ export class NgSwitchCase implements DoCheck {
231237
* @see `NgSwitchCase`
232238
*
233239
*/
234-
@Directive({selector: '[ngSwitchDefault]'})
240+
@Directive({
241+
selector: '[ngSwitchDefault]',
242+
standalone: true,
243+
})
235244
export class NgSwitchDefault {
236245
constructor(
237246
viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,

‎packages/common/src/directives/ng_template_outlet.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ import {Directive, EmbeddedViewRef, Injector, Input, OnChanges, SimpleChanges, T
3232
*
3333
* @publicApi
3434
*/
35-
@Directive({selector: '[ngTemplateOutlet]'})
35+
@Directive({
36+
selector: '[ngTemplateOutlet]',
37+
standalone: true,
38+
})
3639
export class NgTemplateOutlet implements OnChanges {
3740
private _viewRef: EmbeddedViewRef<any>|null = null;
3841

‎packages/common/test/directives/ng_class_spec.ts

+18
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9+
import {NgClass} from '@angular/common';
910
import {Component} from '@angular/core';
1011
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
1112

@@ -391,6 +392,23 @@ import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
391392
expect(leading.className).toBe('foo');
392393
expect(trailing.className).toBe('foo');
393394
});
395+
396+
it('should be available as a standalone directive', () => {
397+
@Component({
398+
selector: 'test-component',
399+
imports: [NgClass],
400+
template: `<div trailing-space [ngClass]="{foo: applyClasses}"></div>`,
401+
standalone: true,
402+
})
403+
class TestComponent {
404+
applyClasses = true;
405+
}
406+
407+
const fixture = TestBed.createComponent(TestComponent);
408+
fixture.detectChanges();
409+
410+
expect(fixture.nativeElement.firstChild.className).toBe('foo');
411+
});
394412
});
395413
});
396414
}

‎packages/common/test/directives/ng_component_outlet_spec.ts

+26
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,32 @@ describe('insert/remove', () => {
267267

268268
expect(fixture.nativeElement).toHaveText('Value: child');
269269
}));
270+
271+
it('should be available as a standalone directive', () => {
272+
@Component({
273+
standalone: true,
274+
template: 'Hello World',
275+
})
276+
class HelloWorldComp {
277+
}
278+
279+
@Component({
280+
selector: 'test-component',
281+
imports: [NgComponentOutlet],
282+
template: `
283+
<ng-container *ngComponentOutlet="component"></ng-container>
284+
`,
285+
standalone: true,
286+
})
287+
class TestComponent {
288+
component = HelloWorldComp;
289+
}
290+
291+
const fixture = TestBed.createComponent(TestComponent);
292+
fixture.detectChanges();
293+
294+
expect(fixture.nativeElement.textContent).toBe('Hello World');
295+
});
270296
});
271297

272298
const TEST_TOKEN = new InjectionToken('TestToken');

‎packages/common/test/directives/ng_for_spec.ts

+20-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {CommonModule} from '@angular/common';
9+
import {CommonModule, NgForOf} from '@angular/common';
1010
import {Component} from '@angular/core';
1111
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
1212
import {By} from '@angular/platform-browser/src/dom/debug/by';
@@ -389,6 +389,25 @@ let thisArg: any;
389389
detectChangesAndExpectText('efh');
390390
}));
391391
});
392+
393+
it('should be available as a standalone directive', () => {
394+
@Component({
395+
selector: 'test-component',
396+
imports: [NgForOf],
397+
template: `
398+
<ng-container *ngFor="let item of items">{{ item }}|</ng-container>
399+
`,
400+
standalone: true,
401+
})
402+
class TestComponent {
403+
items = [1, 2, 3];
404+
}
405+
406+
const fixture = TestBed.createComponent(TestComponent);
407+
fixture.detectChanges();
408+
409+
expect(fixture.nativeElement.textContent).toBe('1|2|3|');
410+
});
392411
});
393412
}
394413

‎packages/common/test/directives/ng_if_spec.ts

+21-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {CommonModule, ɵgetDOM as getDOM} from '@angular/common';
9+
import {CommonModule, NgIf, ɵgetDOM as getDOM} from '@angular/common';
1010
import {Component} from '@angular/core';
1111
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
1212
import {By} from '@angular/platform-browser/src/dom/debug/by';
@@ -250,6 +250,26 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
250250
fixture.detectChanges();
251251
expect(fixture.nativeElement).toHaveText('false');
252252
}));
253+
254+
it('should be available as a standalone directive', () => {
255+
@Component({
256+
selector: 'test-component',
257+
imports: [NgIf],
258+
template: `
259+
<div *ngIf="true">Hello</div>
260+
<div *ngIf="false">World</div>
261+
`,
262+
standalone: true,
263+
})
264+
class TestComponent {
265+
}
266+
267+
const fixture = TestBed.createComponent(TestComponent);
268+
fixture.detectChanges();
269+
270+
expect(fixture.nativeElement.textContent).toBe('Hello');
271+
expect(fixture.nativeElement.textContent).not.toBe('World');
272+
});
253273
});
254274

255275
describe('Type guarding', () => {

‎packages/common/test/directives/ng_plural_spec.ts

+21-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {CommonModule, NgLocalization} from '@angular/common';
9+
import {CommonModule, NgLocalization, NgPlural, NgPluralCase} from '@angular/common';
1010
import {Component, Injectable} from '@angular/core';
1111
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
1212
import {expect} from '@angular/platform-browser/testing/src/matchers';
@@ -138,6 +138,26 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
138138
detectChangesAndExpectText('you have a few messages.');
139139
}));
140140
});
141+
142+
it('should be available as a standalone directive', () => {
143+
@Component({
144+
selector: 'test-component',
145+
imports: [NgPlural, NgPluralCase],
146+
template: '<ul [ngPlural]="switchValue">' +
147+
'<ng-template ngPluralCase="=0"><li>no messages</li></ng-template>' +
148+
'<ng-template ngPluralCase="=1"><li>one message</li></ng-template>' +
149+
'</ul>',
150+
standalone: true,
151+
})
152+
class TestComponent {
153+
switchValue = 1;
154+
}
155+
156+
const fixture = TestBed.createComponent(TestComponent);
157+
fixture.detectChanges();
158+
159+
expect(fixture.nativeElement.textContent).toBe('one message');
160+
});
141161
}
142162

143163
@Injectable()

‎packages/common/test/directives/ng_style_spec.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {CommonModule} from '@angular/common';
9+
import {CommonModule, NgStyle} from '@angular/common';
1010
import {Component} from '@angular/core';
1111
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
1212

@@ -210,6 +210,23 @@ import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
210210
const target: HTMLElement = fixture.nativeElement.querySelector('div');
211211
expect(getComputedStyle(target).getPropertyValue('width')).toEqual('100px');
212212
});
213+
214+
it('should be available as a standalone directive', () => {
215+
@Component({
216+
selector: 'test-component',
217+
imports: [NgStyle],
218+
template: `<div [ngStyle]="{'width.px': expr}"></div>`,
219+
standalone: true,
220+
})
221+
class TestComponent {
222+
expr = 400;
223+
}
224+
225+
const fixture = TestBed.createComponent(TestComponent);
226+
fixture.detectChanges();
227+
228+
expectNativeEl(fixture).toHaveCssStyle({'width': '400px'});
229+
});
213230
});
214231
}
215232

‎packages/common/test/directives/ng_switch_spec.ts

+28-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {CommonModule} from '@angular/common';
9+
import {CommonModule, NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';
1010
import {Attribute, Component, Directive, TemplateRef, ViewChild,} from '@angular/core';
1111
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
1212
import {expect} from '@angular/platform-browser/testing/src/matchers';
@@ -121,6 +121,33 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
121121
});
122122
});
123123

124+
it('should be available as standalone directives', () => {
125+
@Component({
126+
selector: 'test-component',
127+
imports: [NgSwitch, NgSwitchCase, NgSwitchDefault],
128+
template: '<ul [ngSwitch]="switchValue">' +
129+
'<li *ngSwitchCase="\'a\'">when a</li>' +
130+
'<li *ngSwitchDefault>when default</li>' +
131+
'</ul>',
132+
standalone: true,
133+
})
134+
class TestComponent {
135+
switchValue = 'a';
136+
}
137+
138+
const fixture = TestBed.createComponent(TestComponent);
139+
fixture.detectChanges();
140+
expect(fixture.nativeElement).toHaveText('when a');
141+
142+
fixture.componentInstance.switchValue = 'b';
143+
fixture.detectChanges();
144+
expect(fixture.nativeElement).toHaveText('when default');
145+
146+
fixture.componentInstance.switchValue = 'c';
147+
fixture.detectChanges();
148+
expect(fixture.nativeElement).toHaveText('when default');
149+
});
150+
124151
describe('corner cases', () => {
125152
it('should not create the default case if another case matches', () => {
126153
const log: string[] = [];

‎packages/common/test/directives/ng_template_outlet_spec.ts

+20-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {CommonModule} from '@angular/common';
9+
import {CommonModule, NgTemplateOutlet} from '@angular/common';
1010
import {Component, ContentChildren, Directive, Inject, Injectable, InjectionToken, Injector, NO_ERRORS_SCHEMA, OnDestroy, Provider, QueryList, TemplateRef} from '@angular/core';
1111
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
1212
import {expect} from '@angular/platform-browser/testing/src/matchers';
@@ -299,6 +299,25 @@ describe('NgTemplateOutlet', () => {
299299
Injector.create({providers: [{provide: templateToken, useValue: 'world'}]});
300300
detectChangesAndExpectText('Hello world');
301301
}));
302+
303+
it('should be available as a standalone directive', () => {
304+
@Component({
305+
selector: 'test-component',
306+
imports: [NgTemplateOutlet],
307+
template: `
308+
<ng-template #tpl>Hello World</ng-template>
309+
<ng-container *ngTemplateOutlet="tpl"></ng-container>
310+
`,
311+
standalone: true,
312+
})
313+
class TestComponent {
314+
}
315+
316+
const fixture = TestBed.createComponent(TestComponent);
317+
fixture.detectChanges();
318+
319+
expect(fixture.nativeElement.textContent).toBe('Hello World');
320+
});
302321
});
303322

304323
const templateToken = new InjectionToken<string>('templateToken');

0 commit comments

Comments
 (0)
Please sign in to comment.