# Using Green Core components with Angular

There are a few things you need to know about and set up in order to use the Green Core web components with Angular. This document covers how to use the components, handle element name scoping, form controls and how to integrate with Angulars router. It is recommended to at least skim through this document before you begin.

## Wrappers 🌯

Angular has support for using web components directly by using [`CUSTOM_ELEMENTS_SCHEMA`](https://angular.dev/guide/components/advanced-configuration#custom-element-schemas) in your module or component. However, this also disables type-checking for any non-angular components in your templates, which can lead to a frustrating developer experience.

To improve this situation, Green provides a wrapper library for Angular. To use it, install `@sebgroup/green-core-ng` instead of `@sebgroup/green-core` in your project. The wrapper library is automatically built, versioned and published alongside Core, and has `@sebgroup/green-core` defined as a sub-dependency, so you typically only need to have `@sebgroup/green-core-ng` as a direct dependency. Since the wrapper components are tightly mapped to their underlying counterparts, it's important that the versions of these two packages are always in sync in your project.

To migrate existing code from using `@sebgroup/green-core` with `CUSTOM_ELEMENTS_SCHEMA`, check out the [migration section](#migrating-from-custom_elements_schema) at the end of this document.

### Status: Beta

Even though `@sebgroup/green-core-ng` follows the same semantic version number as `@sebgroup/green-core`, it is still considered to be in beta for as long as this sentance remains here.

## Scoping

You also need to handle Green Core's [element name scoping](/docs/concepts-scoping--docs). There are two ways to do this:

- **Use the `GdsCoreRenderer` custom renderer** (preferred)<br/>
  This renderer automatically applies scoping to all Green Core elements in your template.
- **Use the `GdsCoreScopeModule` module**<br/>
  This module provides a directive, `*gdsCoreScope` that you can use to apply scoping to individual sections of your template.

The renderer is the most convenient way to use Green Core components with Angular, but the directive can provide more explicit control when needed, or should the renderer conflict with other custom renderers, or cause any other unexpected side effects.

### Using `GdsCoreRenderer`

The `GdsCoreRenderer` is a custom renderer that automatically applies scoping to all Green Core elements in your template. It does this by overriding the call to `document.createElement()` and applying the scoping suffix to the element names before creation. This is the easiest way to use Green Core components in your Angular application.

**In your module:**

```ts

@NgModule({
    // Provides `GdsCoreRenderer` as a custom renderer
    providers: [provideCoreRenderer()],
})
```

Or, if you are only using standalone components, you can either create a root app module and provide the renderer there, or you can provide it in bootstrapping:

```ts
// app.config.ts
const appConfig: ApplicationConfig = {
  providers: [...other providers..., provideCoreRenderer()],
};

// main.ts
bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));
```

**In your component:**

```ts
// Import standalone wrapper component

@Component({
    standalone: true,
    imports: [GdsButtonComponent],
})
export class MyComponent {}
```

Or, you can get everything from a module:

```ts

@Component({
    standalone: true,
    imports: [GreenCoreNgModule],
})
export class MyComponent {}
```

Now you can use Green Core components in your template like any other elements, and intellisense and type checking should work as expected.

```html
<gds-button (click)="handleEvent($event)">Click me!</gds-button>
```

#### Using the custom renderer with Angular animations

If you also need to use Angular animations, you need to use a special version of the provider. This is because Angular animations also use a custom renderer under the hood, so we need a bit of specialized initialization to make sure both the Green Core renderer and the Angular animations renderer can coexist and do their things.

All you need to do on your end is to use `provideCoreRendererWithAnimations()` instead of `provideCoreRenderer()`.

```ts

@NgModule({
    imports: [BrowserAnimationsModule] // You also need to make sure you have imported the `BrowserAnimationsModule` module
    providers: [provideCoreRendererWithAnimations()],
})
```

### Using `GdsCoreScopeModule`

The `GdsCoreScopeModule` is a module that provides a directive, `*gdsCoreScope`, that you can use to only apply scoping to individual sections in your template. This can be useful if you need more explicit control over which elements are scoped, or if the `GdsCoreRenderer` is causing any issues.

**In your module:**

```ts

@NgModule({
    // Add the GdsCoreScopeModule to the `imports` array
    imports: [GdsCoreScopeModule],
})
```
Use the web component in your template with the `*gdsCoreScope` directive.

**In your template:**

```html
<gds-button *gdsCoreScope (click)="handleEvent($event)">Click me!</gds-button>

// Or, to scope a whole section:
<div *gdsCoreScope>
  <gds-input label="Name"></gds-input>
  <gds-button (click)="submit()">Submit</gds-button>
</div>
```

## Form controls

The wrappers for Green Core form controls, such as `<gds-input>`, `<gds-select>`, and `<gds-checkbox>`, implement Angular's `ControlValueAccessor` interface. This means that they can be used seamlessly with Angular forms, both template-driven and reactive forms. No additional directives or configuration is needed.

## Routing

The wrapper library also provides support for Angular's `RouterLink` directive. This allows you to use Green Core link components, such as `<gds-link>`, `<gds-menu-button>`, and `<gds-breadcrumb>`, with Angular's router.

**In your template:**<br/>
This assumes you have routes already defined in `routes`.

```html
<gds-menu-button
  *ngFor="let route of routes"
  [routerLink]="route.path"
  routerLinkActive
>
  {{ route.data?.name }}
</gds-menu-button>
```

This should work as expected, with the `href` attribute being set automatically based on the `routerLink` value, and the `selected` property being set based on the active route.

## Migrating from CUSTOM_ELEMENTS_SCHEMA

To migrate an existing Angular project that uses Green Core components with `CUSTOM_ELEMENTS_SCHEMA`, you need to do the following steps:

1. **Remove `CUSTOM_ELEMENTS_SCHEMA`** from your module or component schemas.
2. **Install `@sebgroup/green-core-ng`** and replace any imports of `@sebgroup/green-core` with `@sebgroup/green-core-ng`.\
   Example:
   ```ts
    // Before
    import { GdsButton } from '@sebgroup/green-core'

    // After
    import { GdsButtonComponent } from '@sebgroup/green-core-ng'

    @Component({
        imports: [GdsButtonComponent], // Add to imports array
    })
    // ...
    ```
3. **Set up scoping** using either the `GdsCoreRenderer` or the `GdsCoreScopeModule` as described above.
4. You can also remove any usages of `NggCoreFormsModule` and `NggCoreRoutingModule`, as these aspects are now handled out of the box.