New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@cerebral/angular

Package Overview
Dependencies
Maintainers
6
Versions
280
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cerebral/angular

Angular view for Cerebral

4.3.1
latest
Source
npm
Version published
Maintainers
6
Created
Source

@cerebral/angular

Angular integration for Cerebral state management.

Installation

npm install @cerebral/angular @angular/core @angular/platform-browser

Usage

AppService

AppService is the core service that creates and exposes the Cerebral controller to your Angular application.

Setup in Angular App
// app.config.ts
import { ApplicationConfig } from '@angular/core'
import { provideAnimations } from '@angular/platform-browser/animations'
import { provideRouter } from '@angular/router'
import { AppService } from '@cerebral/angular'
import { SomeService } from './some.service'
import { routes } from './app.routes'

// Create a Cerebral app factory
export function createCerebralApp(someService: SomeService) {
  return new AppService({
    state: {
      count: 0,
      items: []
    },
    sequences: {
      increment: [
        ({ store, get }) => store.set('count', get(state`count`) + 1)
      ],
      decrement: [({ store, get }) => store.set('count', get(state`count`) - 1)]
    },
    providers: {
      // Provide Angular services to Cerebral
      someService
    }
  })
}

// Provide AppService in your app config
export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideAnimations(),
    {
      provide: AppService,
      useFactory: createCerebralApp,
      deps: [SomeService]
    }
  ]
}

Components

Using the connect decorator

The connect decorator connects Cerebral state and sequences to your components:

import {
  Component,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Inject
} from '@angular/core'
import { state, sequences } from 'cerebral'
import { connect, AppService, CerebralComponent } from '@cerebral/angular'

@Component({
  selector: 'app-counter',
  standalone: true, // In Angular 19+ is this the default
  template: `
    <div>
      <h2>Count: {{ count }}</h2>
      <button (click)="increment()">+</button>
      <button (click)="decrement()">-</button>
    </div>
  `,
  // OnPush change detection is required for optimal performance
  changeDetection: ChangeDetectionStrategy.OnPush
})
@connect({
  count: state`count`,
  increment: sequences`increment`,
  decrement: sequences`decrement`
})
export class CounterComponent extends CerebralComponent {
  // Properly declare connected properties with TypeScript
  count!: number
  increment!: () => void
  decrement!: () => void

  constructor(
    @Inject(ChangeDetectorRef) cdr: ChangeDetectorRef,
    @Inject(AppService) app: AppService
  ) {
    super(cdr, app)
  }
}
Working with Parent/Child Components

For parent-child component relationships, ensure child components are properly imported:

import {
  Component,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Inject
} from '@angular/core'
import { state, sequences } from 'cerebral'
import { connect, AppService, CerebralComponent } from '@cerebral/angular'
import { ChildComponent } from './child.component'

@Component({
  selector: 'app-parent',
  standalone: true,
  imports: [ChildComponent],
  template: `
    <div>
      <h1>Parent</h1>
      <app-child [data]="items"></app-child>
      <button (click)="addItem()">Add Item</button>
    </div>
  `,
  // Change detection needs to be set to OnPush
  changeDetection: ChangeDetectionStrategy.OnPush
})
@connect({
  items: state`items`,
  addItem: sequences`addItem`
})
export class ParentComponent extends CerebralComponent {
  items!: any[]
  addItem!: () => void

  constructor(
    @Inject(ChangeDetectorRef) cdr: ChangeDetectorRef,
    @Inject(AppService) app: AppService
  ) {
    super(cdr, app)
  }
}

Advanced Features

Using Angular Services in Cerebral Sequences

You can inject Angular services into your Cerebral sequences using providers:

// app.config.ts
import { HttpClient } from '@angular/common/http'
import { ApplicationConfig } from '@angular/core'
import { AppService } from '@cerebral/angular'

export function createCerebralApp(httpClient: HttpClient) {
  return new AppService({
    state: {
      data: null,
      loading: false,
      error: null
    },
    sequences: {
      fetchData: [
        ({ store }) => store.set('loading', true),
        async ({ http }) => {
          try {
            const response = await http.get('/api/data').toPromise()
            return { response }
          } catch (error) {
            return { error }
          }
        },
        ({ store, props }) => {
          if (props.error) {
            store.set('error', props.error)
          } else {
            store.set('data', props.response)
          }
          store.set('loading', false)
        }
      ]
    },
    providers: {
      http: httpClient
    }
  })
}

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: AppService,
      useFactory: createCerebralApp,
      deps: [HttpClient]
    }
  ]
}
Using Computed Values

Cerebral uses functions to compute derived state values:

import { state } from 'cerebral'
import { AppService } from '@cerebral/angular'

// 1. Define types for better type safety
type Item = { id: number; name: string }
type AppState = {
  items: Item[]
  filter: string
  filteredItems?: Item[]
}

// 2. Define the computed function
const filteredItems = (get: any) => {
  const items = get(state`items`)
  const filter = get(state`filter`)
  return items.filter((item: Item) =>
    filter ? item.name.includes(filter) : true
  )
}

// 3. Create your app with computed properties
const app = new AppService({
  state: {
    items: [],
    filter: '',
    filteredItems // Attach computed to state
  } as AppState,
  sequences: {
    // Define your sequences here
  }
})

// 4. Use in component
@Component({
  standalone: true
  // ...component config
})
@connect({
  filteredItems: state`filteredItems` // Access via state tag or proxy
})
export class ListComponent extends CerebralComponent {
  // Declare with proper type
  filteredItems!: Item[]
}

Computed values automatically track their dependencies and only recalculate when necessary, improving performance for derived state.

Troubleshooting

Common Issues

  • State updates not reflected in components

    • Make sure your component uses ChangeDetectionStrategy.OnPush
    • Check that you've extended CerebralComponent
    • Verify you're using @Inject() for dependency injection
  • TypeScript errors with connected properties

    • Always declare connected properties with the correct type and ! assertion
    • Example: count!: number;
  • Angular directives not working

    • When using standalone components, remember to import needed directives
    • Example: imports: [NgIf, NgFor, CommonModule]
  • Component not updating after state change

    • Check if you need to call app.flush() after sequence execution in tests
    • In components, sequences are automatically flushed

FAQs

Package last updated on 25 Mar 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts