analogjs / analog

The fullstack meta-framework for Angular. Powered by Vite and Nitro
https://analogjs.org
MIT License
2.48k stars 234 forks source link

Support ng-content inside the astro-angular package #917

Open thebspin opened 5 months ago

thebspin commented 5 months ago

Which scope/s are relevant/related to the feature request?

astro-angular

Information

Content projection is done easily inside Angular itself using <ng-content />. Anything added inside the opening and closing components tags would be rendered here.

For example:

<my-card variant="lg">
Hello World
</my-card>

This would render the my-card with any attributes given to the component. And additionally if the component has a ng-content slot defined it would render my Hello world text inside of here.

I would expect that in Astro the same behaviour would happen but i understand it does not. If we would support this we would get even more Angular goodies inside Astro.

Besides having normal slots, you can also have named slots. For example this template:

    <h2>Multi-slot content projection</h2>

    Default:
    <ng-content></ng-content>

    Question:
    <ng-content select="[question]"></ng-content>

You would render the corresponding content of it using an attribute like this:

<app-zippy-multislot>
  <p question>
    Is content projection cool?
  </p>
  <p>Let's learn about content projection!</p>
</app-zippy-multislot>

This would probably be more tricky to support, but maybe this could also be tackled?

Describe any alternatives/workarounds you're currently using

Instead of ng-content you could make inputs for everything, but this will not give the same freedom and therefor will only work for simple components.

I would be willing to submit a PR to fix this issue

(I have no idea where to start tho and it might be to hard for me)

seeplusplus commented 5 months ago

@thebspin A good place to start might be here https://github.com/analogjs/analog/blob/beta/packages/astro-angular/src/server.ts#L76-L82 There is an unused _children property on this function. See here where that same property (called slot) is being used.

It doesn't look like any of the Angular functions being called in the rest of renderStaticMarkup can accept children/slots but there is this method in @angular/core:

https://github.com/angular/angular/blob/e02bcf89cf77c3118c649a7db68e66a78f16155c/packages/core/src/render3/component.ts#L73

However this requires an EnvironmentInjector. I think these might be the pieces needed, but I'm not sure how to put them together

thebspin commented 4 months ago

@seeplusplus

Thanks, today i had some time and tried this route (seems the most logical) but unfortunaly when calling the createComponent function i get an Angular error i have yet to solve. NG0407: Angular was not able to inject a renderer (RendererFactory2). Likely this is due to a broken DI hierarchy. Make sure that any injector used to create this component has a correct parent. I do pass the bootstrap.injector as an option and that should work but it doesn't..

EDIT: it's probably because bootstrap.injector is empty, where bootstrap is the result of the bootstrapApplication function that's already in place