@@ -7193,4 +7193,140 @@ describe('di', () => {
71937193 ) ;
71947194 } ) ;
71957195 } ) ;
7196+
7197+ describe ( 'control flow + viewProviders' , ( ) => {
7198+ it ( 'should not allow projected content to see viewProviders when wrapped in @if' , ( ) => {
7199+ const token = new InjectionToken < string > ( 'token' ) ;
7200+
7201+ @Component ( {
7202+ selector : 'app-child-component' ,
7203+ standalone : true ,
7204+ template : '{{value}}' ,
7205+ } )
7206+ class ChildComponent {
7207+ value = inject ( token ) ;
7208+ }
7209+
7210+ @Component ( {
7211+ selector : 'app-provider-component' ,
7212+ standalone : true ,
7213+ imports : [ ] ,
7214+ providers : [ { provide : token , useValue : 'provider' } ] ,
7215+ viewProviders : [ { provide : token , useValue : 'viewProvider' } ] ,
7216+ template : `
7217+ <div>
7218+ Projected<br />
7219+ <ng-content></ng-content>
7220+ </div>
7221+ ` ,
7222+ } )
7223+ class ProviderComponent { }
7224+
7225+ @Component ( {
7226+ selector : 'app-test-new-flow' ,
7227+ standalone : true ,
7228+ imports : [ ProviderComponent , ChildComponent ] ,
7229+ template : `
7230+ <app-provider-component>
7231+ @if (flag) {
7232+ <app-child-component />
7233+ }
7234+ </app-provider-component>
7235+ ` ,
7236+ } )
7237+ class TestNewFlowComponent {
7238+ flag = true ;
7239+ }
7240+
7241+ @Component ( {
7242+ selector : 'app-test-old-flow' ,
7243+ standalone : true ,
7244+ imports : [ ProviderComponent , ChildComponent , CommonModule ] ,
7245+ template : `
7246+ <app-provider-component>
7247+ <app-child-component *ngIf="flag" />
7248+ </app-provider-component>
7249+ ` ,
7250+ } )
7251+ class TestOldFlowComponent {
7252+ flag = true ;
7253+ }
7254+
7255+ // Test old syntax it's ok
7256+ const oldFixture = TestBed . createComponent ( TestOldFlowComponent ) ;
7257+ oldFixture . detectChanges ( ) ;
7258+ expect ( oldFixture . nativeElement . textContent ) . toContain ( 'provider' ) ;
7259+ expect ( oldFixture . nativeElement . textContent ) . not . toContain ( 'viewProvider' ) ;
7260+
7261+ // Test that the new syntax behaves like the old one
7262+ const newFixture = TestBed . createComponent ( TestNewFlowComponent ) ;
7263+ newFixture . detectChanges ( ) ;
7264+ expect ( newFixture . nativeElement . textContent ) . toContain ( 'provider' ) ;
7265+ expect ( newFixture . nativeElement . textContent ) . not . toContain ( 'viewProvider' ) ;
7266+ } ) ;
7267+
7268+ it ( 'should allow a directive in an @if block to inject a token from viewProviders' , ( ) => {
7269+ const TOKEN = new InjectionToken < string > ( 'token' ) ;
7270+
7271+ @Directive ( {
7272+ selector : '[testDir]' ,
7273+ standalone : true ,
7274+ } )
7275+ class TestDir {
7276+ value = inject ( TOKEN ) ;
7277+ }
7278+
7279+ @Component ( {
7280+ selector : 'test-comp' ,
7281+ standalone : true ,
7282+ imports : [ TestDir ] ,
7283+ viewProviders : [ { provide : TOKEN , useValue : 'view-value' } ] ,
7284+ template : `
7285+ @if (true) {
7286+ <div testDir></div>
7287+ }
7288+ ` ,
7289+ } )
7290+ class TestComp {
7291+ @ViewChild ( TestDir ) testDir ! : TestDir ;
7292+ }
7293+
7294+ const fixture = TestBed . createComponent ( TestComp ) ;
7295+ fixture . detectChanges ( ) ;
7296+
7297+ expect ( fixture . componentInstance . testDir . value ) . toBe ( 'view-value' ) ;
7298+ } ) ;
7299+
7300+ it ( 'should allow a directive in nested @if blocks to inject a token from viewProviders' , ( ) => {
7301+ const TOKEN = new InjectionToken < string > ( 'token' ) ;
7302+
7303+ @Directive ( {
7304+ selector : '[testDir]' ,
7305+ standalone : true ,
7306+ } )
7307+ class TestDir {
7308+ value = inject ( TOKEN ) ;
7309+ }
7310+
7311+ @Component ( {
7312+ selector : 'test-comp' ,
7313+ standalone : true ,
7314+ imports : [ TestDir ] ,
7315+ viewProviders : [ { provide : TOKEN , useValue : 'view-value' } ] ,
7316+ template : `
7317+ @if (true) {
7318+ <div testDir></div>
7319+ }
7320+ ` ,
7321+ } )
7322+ class TestComp {
7323+ @ViewChild ( TestDir ) testDir ! : TestDir ;
7324+ }
7325+
7326+ const fixture = TestBed . createComponent ( TestComp ) ;
7327+ fixture . detectChanges ( ) ;
7328+
7329+ expect ( fixture . componentInstance . testDir . value ) . toBe ( 'view-value' ) ;
7330+ } ) ;
7331+ } ) ;
71967332} ) ;
0 commit comments