Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/compiler-cli/src/ngtsc/typecheck/src/oob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,8 @@ export class OutOfBandDiagnosticRecorderImpl implements OutOfBandDiagnosticRecor
const blockName = controlFlowNode.nameSpan.toString().trim();
const lines = [
`Node matches the "${slotSelector}" slot of the "${componentName}" component, but will not be projected into the specific slot because the surrounding ${blockName} has more than one node at its root. To project the node in the right slot, you can:\n`,
`1. Wrap the content of the ${blockName} block in an <ng-container/> that matches the "${slotSelector}" selector.`,
`2. Split the content of the ${blockName} block across multiple ${blockName} blocks such that each one only has a single projectable node at its root.`,
`1. Wrap the content of the ${blockName} block in an <ng-container ngProjectAs="${slotSelector}"> to explicitly target the "${slotSelector}" slot. Use this when all nodes in the block should be projected into the same slot.`,
`2. Split the content of the ${blockName} block across multiple ${blockName} blocks such that each one only has a single projectable node at its root. Use this when nodes in the block target different slots.`,
`3. Remove all content from the ${blockName} block, except for the node being projected.`,
];

Expand Down
36 changes: 36 additions & 0 deletions packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6926,6 +6926,42 @@ suppress
);
});

it('should suggest ngProjectAs in the error message for targeted slots', () => {
env.write(
'test.ts',
`
import {Component} from '@angular/core';

@Component({
selector: 'comp',
template: '<ng-content select="[foo]"/> <ng-content/>',
})
class Comp {}

@Component({
imports: [Comp],
template: \`
<comp>
@if (true) {
<div foo></div>
<span>other content</span>
}
</comp>
\`,
})
class TestCmp {}
`,
);

const diags = env
.driveDiagnostics()
.map((d) => ts.flattenDiagnosticMessageText(d.messageText, ''));
expect(diags.length).toBe(1);
expect(diags[0]).toContain(`ngProjectAs="[foo]"`);
expect(diags[0]).toContain(`all nodes in the block should be projected into the same slot`);
expect(diags[0]).toContain(`nodes in the block target different slots`);
});

it('should not report when there is only one root node', () => {
env.write(
'test.ts',
Expand Down
Loading