Skip to content

feat(core): add support for fallback content in ng-content - #54854

Closed
crisbeto wants to merge 6 commits into
angular:mainfrom
crisbeto:ng-content-fallback
Closed

feat(core): add support for fallback content in ng-content#54854
crisbeto wants to merge 6 commits into
angular:mainfrom
crisbeto:ng-content-fallback

Conversation

@crisbeto

Copy link
Copy Markdown
Member

Adds the ability to specify content that Angular should fall back to if nothing is projected into an ng-content slot. For example, if we have the following setup

@Component({
  selector: 'my-comp',
  template: `
    <ng-content select="header">Default header</ng-content>
    <ng-content select="footer">Default footer</ng-content>
  `
})
class MyComp {}

@Component({
  template: `
    <my-comp>
      <footer>New footer</footer>
    </my-comp>
  `
})
class MyApp {}

The instance of my-comp in the app will have the default header and the new footer.

Note: Angular's content projection happens during creation time. This means that dynamically changing the contents of the slot will not cause the default content to show up, e.g. if a if block goes from true to false.

Fixes #12530.

@crisbeto crisbeto added action: review The PR is still awaiting reviews from at least one requested reviewer area: core Issues related to the framework runtime target: major This PR is targeted for the next major release labels Mar 14, 2024
@ngbot ngbot Bot added this to the Backlog milestone Mar 14, 2024
@angular-robot angular-robot Bot added the detected: feature PR contains a feature commit label Mar 14, 2024
@crisbeto
crisbeto marked this pull request as ready for review March 14, 2024 08:51
@pullapprove
pullapprove Bot requested a review from atscott March 14, 2024 08:51
@crisbeto crisbeto modified the milestones: Backlog, v18-candidates Mar 14, 2024
Comment thread packages/core/test/acceptance/content_spec.ts Outdated
@crisbeto
crisbeto force-pushed the ng-content-fallback branch from 692a1f8 to 2448101 Compare March 14, 2024 20:19
Comment thread packages/core/src/render3/instructions/projection.ts Outdated
Comment thread packages/core/test/acceptance/content_spec.ts Outdated
Comment thread packages/core/test/acceptance/content_spec.ts Outdated

@pkozlowski-opensource pkozlowski-opensource left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall, thank you for adding very thorough tests. The only addition I could think of are tests for re-projection with the default content.

Updates the template AST to capture the content of `ng-content` elements instead of throwing an error.
Updates the code that generates the `projection` instruction to pass the template function containing the default content into it.
…o template type checker

Adds logic to ingest the content of an `ng-content` element in the template type checker. We treat `ng-content` as a `ScopedNode`, because its content is inserted conditionally.
Adds the ability to specify content that Angular should fall back to if nothing is projected into an `ng-content` slot. For example, if we have the following setup

```
@component({
  selector: 'my-comp',
  template: `
    <ng-content select="header">Default header</ng-content>
    <ng-content select="footer">Default footer</ng-content>
  `
})
class MyComp {}

@component({
  template: `
    <my-comp>
      <footer>New footer</footer>
    </my-comp>
  `
})
class MyApp {}
```

The instance of `my-comp` in the app will have the default header and the new footer.

**Note:** Angular's content projection happens during creation time. This means that dynamically changing the contents of the slot will not cause the default content to show up, e.g. if a `if` block goes from `true` to `false`.

Fixes angular#12530.
Moves the logic that declares a template out into a separate function so that it can be reused in other places like control flow and defer, without having to call directly into the `template` instruction.
… content

Passes the attributes of the `ng-content` element to the container that is created for the fallback content so that it can be re-projected into the same slot.
@crisbeto
crisbeto force-pushed the ng-content-fallback branch from 2448101 to 623a491 Compare March 25, 2024 14:13

@atscott atscott left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewed-for: language-service

@crisbeto crisbeto added action: merge The PR is ready for merge by the caretaker and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Mar 25, 2024
@dylhunn

dylhunn commented Mar 26, 2024

Copy link
Copy Markdown
Contributor

This PR was merged into the repository by commit 2fc11ea.

@dylhunn dylhunn closed this in c734808 Mar 26, 2024
dylhunn pushed a commit that referenced this pull request Mar 26, 2024
…54854)

Updates the code that generates the `projection` instruction to pass the template function containing the default content into it.

PR Close #54854
dylhunn pushed a commit that referenced this pull request Mar 26, 2024
…o template type checker (#54854)

Adds logic to ingest the content of an `ng-content` element in the template type checker. We treat `ng-content` as a `ScopedNode`, because its content is inserted conditionally.

PR Close #54854
dylhunn pushed a commit that referenced this pull request Mar 26, 2024
Adds the ability to specify content that Angular should fall back to if nothing is projected into an `ng-content` slot. For example, if we have the following setup

```
@component({
  selector: 'my-comp',
  template: `
    <ng-content select="header">Default header</ng-content>
    <ng-content select="footer">Default footer</ng-content>
  `
})
class MyComp {}

@component({
  template: `
    <my-comp>
      <footer>New footer</footer>
    </my-comp>
  `
})
class MyApp {}
```

The instance of `my-comp` in the app will have the default header and the new footer.

**Note:** Angular's content projection happens during creation time. This means that dynamically changing the contents of the slot will not cause the default content to show up, e.g. if a `if` block goes from `true` to `false`.

Fixes #12530.

PR Close #54854
dylhunn pushed a commit that referenced this pull request Mar 26, 2024
#54854)

Moves the logic that declares a template out into a separate function so that it can be reused in other places like control flow and defer, without having to call directly into the `template` instruction.

PR Close #54854
dylhunn pushed a commit that referenced this pull request Mar 26, 2024
… content (#54854)

Passes the attributes of the `ng-content` element to the container that is created for the fallback content so that it can be re-projected into the same slot.

PR Close #54854
@angular-automatic-lock-bot

Copy link
Copy Markdown

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot Bot locked and limited conversation to collaborators Apr 26, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

action: merge The PR is ready for merge by the caretaker area: core Issues related to the framework runtime detected: feature PR contains a feature commit target: major This PR is targeted for the next major release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ng-content default content

4 participants