Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
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
35 changes: 16 additions & 19 deletions packages/astro-angular/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ yarn add @analogjs/astro-angular
### Install the necessary Angular dependencies

```sh
yarn add @angular-devkit/build-angular @angular/{animations,common,compiler-cli,compiler,core,language-service,forms,platform-browser,platform-browser-dynamic,platform-server} rxjs zone.js tslib
npm install @angular/build @angular/{animations,common,compiler-cli,compiler,core,language-service,forms,platform-browser,platform-server} rxjs tslib --save
```

### Adding the integration
Expand Down Expand Up @@ -178,28 +178,27 @@ export default defineConfig({
The Astro Angular integration **only** supports rendering standalone components:

```ts
import { NgIf } from '@angular/common';
import { Component, Input } from '@angular/core';

@Component({
selector: 'app-hello',
standalone: true,
imports: [NgIf],
template: `
<p>Hello from Angular!!</p>

<p *ngIf="show">{{ helpText }}</p>
@if (show()) {
<p>{{ helpText() }}</p>
}

<button (click)="toggle()">Toggle</button>
`,
})
export class HelloComponent {
@Input() helpText = 'help';
helpText = input('help');

show = false;
show = signal(false);

toggle() {
this.show = !this.show;
this.show.update((show) => !show);
}
}
```
Expand Down Expand Up @@ -269,7 +268,6 @@ These are `renderProviders` and `clientProviders` respectively. These providers

```ts
import { Component, OnInit, inject } from '@angular/core';
import { NgFor } from '@angular/common';
import { provideHttpClient, HttpClient } from '@angular/common/http';

interface Todo {
Expand All @@ -280,15 +278,15 @@ interface Todo {

@Component({
selector: 'app-todos',
standalone: true,
imports: [NgFor],
template: `
<h2>Todos</h2>

<ul>
<li *ngFor="let todo of todos">
{{ todo.title }}
</li>
@for (todo of todos(); track todo.id) {
<li>
{{ todo.title }}
</li>
}
</ul>
`,
})
Expand All @@ -297,12 +295,12 @@ export class TodosComponent implements OnInit {
static renderProviders = [TodosComponent.clientProviders];

http = inject(HttpClient);
todos: Todo[] = [];
todos = signal<Todo[]>([]);

ngOnInit() {
this.http
.get<Todo[]>('https://jsonplaceholder.typicode.com/todos')
.subscribe((todos) => (this.todos = todos));
.subscribe((todos) => this.todos.set(todos));
}
}
```
Expand All @@ -311,15 +309,13 @@ export class TodosComponent implements OnInit {

To use components with MDX pages, you must install and configure MDX support by following the Astro integration of [@astrojs/mdx](https://docs.astro.build/en/guides/integrations-guide/mdx/). Your `astro.config.mjs` should now include the `@astrojs/mdx` integration.

> Note: Shiki is the default syntax highlighter for the MDX plugin and is currently unsupported. `astro-angular` will override this with `prism` but you should specify it in the config to prevent warnings or issues.

```js
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import angular from '@analogjs/astro-angular';

export default defineConfig({
integrations: [mdx({ syntaxHighlight: 'prism' }), angular()],
integrations: [mdx(), angular()],
});
```

Expand Down Expand Up @@ -360,3 +356,4 @@ import { HelloComponent } from "../../components/hello.component.ts";
## Current Limitations

- Only standalone Angular components in version v14.2+ are supported
- Content projection to island components is not supported
22 changes: 10 additions & 12 deletions packages/astro-angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,16 @@
"@analogjs/vite-plugin-angular": "^2.0.0-beta.8"
},
"peerDependencies": {
"@angular-devkit/build-angular": ">=16.0.0",
"@angular/animations": ">=16.0.0",
"@angular/common": ">=16.0.0",
"@angular/compiler-cli": ">=16.0.0",
"@angular/compiler": ">=16.0.0",
"@angular/core": ">=16.0.0",
"@angular/language-service": ">=16.0.0",
"@angular/platform-browser": ">=16.0.0",
"@angular/platform-browser-dynamic": ">=16.0.0",
"@angular/platform-server": ">=16.0.0",
"rxjs": "^7.5.6",
"zone.js": ">=0.13.3",
"@angular/build": ">=20.0.0",
"@angular/animations": ">=20.0.0",
"@angular/common": ">=20.0.0",
"@angular/compiler-cli": ">=20.0.0",
"@angular/compiler": ">=20.0.0",
"@angular/core": ">=20.0.0",
"@angular/language-service": ">=20.0.0",
"@angular/platform-browser": ">=20.0.0",
"@angular/platform-server": ">=20.0.0",
"rxjs": "^7.8.0",
"tslib": "^2.4.0"
},
"ng-update": {
Expand Down
100 changes: 50 additions & 50 deletions packages/astro-angular/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import 'zone.js';
import {
EnvironmentProviders,
Provider,
reflectComponentType,
ɵComponentType as ComponentType,
provideZonelessChangeDetection,
} from '@angular/core';
import { ApplicationRef, NgZone, createComponent } from '@angular/core';
import { ApplicationRef, createComponent } from '@angular/core';
import { createApplication } from '@angular/platform-browser';
import { Observable, Subject, takeUntil } from 'rxjs';

Expand All @@ -18,63 +18,63 @@ export default (element: HTMLElement) => {
_childHTML?: unknown,
) => {
createApplication({
providers: [...(Component.clientProviders || [])],
providers: [
provideZonelessChangeDetection(),
...(Component.clientProviders || []),
],
}).then((appRef: ApplicationRef) => {
const zone = appRef.injector.get(NgZone);
zone.run(() => {
const componentRef = createComponent(Component, {
environmentInjector: appRef.injector,
hostElement: element,
});
const componentRef = createComponent(Component, {
environmentInjector: appRef.injector,
hostElement: element,
});

const mirror = reflectComponentType(Component);
if (props && mirror) {
for (const [key, value] of Object.entries(props)) {
if (
mirror.inputs.some(
({ templateName, propName }) =>
templateName === key || propName === key,
)
) {
componentRef.setInput(key, value);
}
const mirror = reflectComponentType(Component);
if (props && mirror) {
for (const [key, value] of Object.entries(props)) {
if (
mirror.inputs.some(
({ templateName, propName }) =>
templateName === key || propName === key,
)
) {
componentRef.setInput(key, value);
}
}
}

if (mirror?.outputs.length && props?.['data-analog-id']) {
const destroySubject = new Subject<void>();
element.setAttribute(
'data-analog-id',
props['data-analog-id'] as string,
);
if (mirror?.outputs.length && props?.['data-analog-id']) {
const destroySubject = new Subject<void>();
element.setAttribute(
'data-analog-id',
props['data-analog-id'] as string,
);

mirror.outputs.forEach(({ templateName, propName }) => {
const outputName = templateName || propName;
const component = componentRef.instance as Record<
string,
Observable<unknown>
>;
component[outputName]
.pipe(takeUntil(destroySubject))
.subscribe((detail) => {
const event = new CustomEvent(outputName, {
bubbles: true,
cancelable: true,
composed: true,
detail,
});
element.dispatchEvent(event);
mirror.outputs.forEach(({ templateName, propName }) => {
const outputName = templateName || propName;
const component = componentRef.instance as Record<
string,
Observable<unknown>
>;
component[outputName]
.pipe(takeUntil(destroySubject))
.subscribe((detail) => {
const event = new CustomEvent(outputName, {
bubbles: true,
cancelable: true,
composed: true,
detail,
});
});
element.dispatchEvent(event);
});
});

appRef.onDestroy(() => {
destroySubject.next();
destroySubject.complete();
});
}
appRef.onDestroy(() => {
destroySubject.next();
destroySubject.complete();
});
}

appRef.attachView(componentRef.hostView);
});
appRef.attachView(componentRef.hostView);
});
};
};
22 changes: 2 additions & 20 deletions packages/astro-angular/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,33 +64,15 @@ export default function (options?: AngularOptions): AstroIntegration {
return {
name: '@analogjs/astro-angular',
hooks: {
'astro:config:setup': ({
addRenderer,
config,
isRestart,
updateConfig,
}) => {
if (!isRestart && config.markdown?.syntaxHighlight === 'shiki') {
config.markdown.syntaxHighlight = 'prism';
}

'astro:config:setup': ({ addRenderer, updateConfig }) => {
addRenderer(getRenderer());
updateConfig({
vite: getViteConfiguration(
options?.vite,
) as DeepPartial<ViteUserConfig>,
});
},
'astro:config:done': ({ config }) => {
if (
'markdown' in config &&
config.markdown.syntaxHighlight === 'shiki'
) {
console.warn(
`[warning] The Angular integration doesn't support Shiki syntax highlighting in MDX files. Overriding with Prism.\n
To disable this warning, set the syntaxHighlight option in your astro.config.mjs mdx() integration to 'prism' or false.`,
);
}
'astro:config:done': () => {
if (process.env['NODE_ENV'] === 'production') {
enableProdMode();
}
Expand Down
3 changes: 2 additions & 1 deletion packages/astro-angular/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'zone.js/node';
import type {
ComponentMirror,
EnvironmentProviders,
Expand All @@ -9,6 +8,7 @@ import {
ApplicationRef,
InjectionToken,
reflectComponentType,
provideZonelessChangeDetection,
} from '@angular/core';
import {
BEFORE_APP_SERIALIZED,
Expand Down Expand Up @@ -99,6 +99,7 @@ async function renderToStaticMarkup(
STATIC_PROPS_HOOK_PROVIDER,
provideServerRendering(),
{ provide: ɵSERVER_CONTEXT, useValue: 'analog' },
provideZonelessChangeDetection(),
...(Component.renderProviders || []),
],
},
Expand Down