Skip to content

Angular v0.9 Renderer#878

Merged
gspencergoog merged 6 commits intogoogle:mainfrom
gspencergoog:angular_v0_9
Mar 19, 2026
Merged

Angular v0.9 Renderer#878
gspencergoog merged 6 commits intogoogle:mainfrom
gspencergoog:angular_v0_9

Conversation

@gspencergoog
Copy link
Collaborator

Description

This PR adds the v0.9 Angular renderer and packages it into secondary entry points with appropriate package.json configurations. Additionally, it integrates the a2ui_explorer sample app into the samples/ workspace and verifies application bundle generation fully compiles.

Changes

  • renderers/angular/v0_9/: Added the complete v0.9 Angular code (components and core).
  • renderers/angular/ng-package.json & package.json: Created subpath mappings (@a2ui/angular/v0_9) for standard exports lookup.
  • samples/client/angular/projects/a2ui_explorer/: Imported and decoupled demo-app from Lit, updating for A2uiRendererService bindings and dynamic rendering setup.
  • Config Adjustments: Disabling preserveSymlinks and configuring moduleResolution: "bundler" inside samples workspace configurations to fix subpath resolution for linked packages.

Impact & Risks

  • No Impact to v0.8 Core: v0.9 is completely isolated behind standalone @a2ui/angular/v0_9 node subpaths.
  • Fixed Resolves: Rephrased standard builder linking so application static analysis does not fail.

Testing

  1. Run npx ng build a2ui_explorer successfully in samples/client/angular/ workspace.

gemini-code-assist[bot]

This comment was marked as resolved.

gemini-code-assist[bot]

This comment was marked as resolved.

@google google deleted a comment from gemini-code-assist bot Mar 18, 2026
Copy link
Collaborator

@jacobsimionato jacobsimionato left a comment

Choose a reason for hiding this comment

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

Hey this is great! I think it'd be beneficial to merge this ASAP and happy to defer addressing everything here until after merge if you want.

-c "Google LLC" \
.
.; then
echo "License check failed. To fix this, install addlicense and run it:"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks! This is great.

const bindingsObject: Record<string, any> = {};
if (componentBindings) {
for (const binding of componentBindings) {
// binding is from inputBinding, which typically is { provide: ..., useFactory: ... } or similar in older angular
Copy link
Collaborator

Choose a reason for hiding this comment

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

Lol! Thanks for removing. I assume this was never implemented here, and the bindings are handled some other way?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Correct.

@@ -14,11 +14,10 @@
* limitations under the License.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ha totally unused variable! I'd have a slight preference to exclude all v0.8 changes from this PR, but I can't see how deleting this could break anyone seeing as it's private.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That was my thought process as well. Just worried I'd forget to do it, and it's just cruft.

private context?: ComponentContext;

ngOnInit(): void {
const surface = this.rendererService.surfaceGroup?.getSurface(this.surfaceId());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it still possible to explicitly pass in the rendererService when you create this, e.g. so there can be multiple rendererServices in the same application, potentially in different features, with different catalogs?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, it is still possible to have multiple A2uiRendererService instances in the same application, but the "v0.9 way" to do this is via Angular's Dependency Injection rather than explicitly passing it as a property. We could add an input for it later if that seems more ergonomic, I think.

Gemini example:

How it works with multiple features

If you have different features that need different catalogs or configurations, you can provide a unique A2uiRendererService at the "feature-root" component level.

@Component({
  selector: 'feature-a',
  providers: [
    A2uiRendererService,
    { 
      provide: A2UI_RENDERER_CONFIG, 
      useValue: { catalogs: [CatalogA], ... } 
    }
  ],
  template: `
    <a2ui-v09-component-host surfaceId="surface-a" componentId="root" />
  `
})
export class FeatureAComponent {}

/**
* Extends the generic ComponentApi to include Angular-specific component types.
*/
export interface AngularComponentApi extends ComponentApi {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we call this AngularComponentImplementation instead? I know that the implementation isn't inline directly here, and it's a reference to a class, but conceptually, this does represent the implementation of a component. If I have an instance of this class for e.g. ButtonAngularComponentImplementation, this defines a specific implementation of Button which will always look a certain way.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, done.

/**
* Base class for Angular-specific component catalogs.
*/
export class AngularCatalog extends Catalog<AngularComponentApi> {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we just do this:

export type AngularCatalog = Catalog<AngularComponentApi>;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If we change it to a type, then it will be erased when it's compiled, and then we can't use it as a token in a provider, and we'd have to have a separate injection token. The class makes it both stick around (so we can use it directly in a provider), and gives us a single point where would add helper methods that are available to all catalogs.

@gspencergoog gspencergoog merged commit 3e3e780 into google:main Mar 19, 2026
12 checks passed
@github-project-automation github-project-automation bot moved this from Todo to Done in A2UI Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants