npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ngx-hooks

v0.0.5

Published

Function api for Angular

Downloads

1

Readme

:warning: WARNING: It only works with Angular version >=8.x.x with Ivy render enabled (doesn't work with aot build of old compiler).


version MIT License

Table of Contents

Why Function APIs?

  • More declarative way to write Angular Components, Directives and Services
  • Reuse same functions between different components/directives so no need to create services to splitting out methods to reduce component file or making it reusable.
  • Easy to split up functionality into functions of large component without creating unnecessarily more components.
  • Encourages to write implementation detail free tests

Installation

This library is distributed via npm registry:

npm install --save ngx-hooks

This library has @angular/core and rxjs as peerDependencies.

Typescript Configuration

This package contains uncompiled typescript (.ts) files, you need to configure it manually.

To enable typescript compilation of this package along with your angular project, you need to configure source files in tsconfig.json like:

{
  // ...
  include: ['./node_modules/ngx-hooks/**/*.ts'],
  // ...
}

Usage

Component

Simple usage of function component

import { Component } from '@angular/core';
import { FunctionComponent, NgHooksContext, ref } from 'ngx-hooks';

@Component({
  selector: 'app-component',
  template: '<h1>{{title}}</h1>',
})
@FunctionComponent() // <- to make Function Component
class AppComponent {
  title: string;

  // required by @FunctionComponent() and must be static
  static ngHooks(context: NgHooksContext<AppComponent>) {
    const title = ref('Angular Function APIs');
    return { title };
  }
}

Directive

Simple usage of a function directive which highlights a text with yellow color

import { Directive, ElementRef } from '@angular/core';
import { FunctionDirective, NgHooksContext, inject } from 'ngx-hooks';

@Directive({
  selector: '[highlight]',
})
@FunctionDirective() // <- to make Function Directive
class HighlightDirective {
  // required by @FunctionDirective() and must be static
  static ngHooks(context: NgHooksContext<HighlightDirective>) {
    const elementRef = inject(ElementRef);
    elementRef.nativeElement.style.backgroundColor = 'yellow';
  }
}

Lifecycle

Lifecycle can be used in Function component/directives and Provider or any composed function. It must be used in ngHooks function body or custom compose function body, can't be used in nested callback

import { onDestroy, ref } from 'ngx-hooks';

class AppComponent {
  static ngHooks(context: NgHooksContext<AppComponent>) {
    const count = ref(0);

    const interval = setInterval(() => {
      ref.value++;
    }, 1000);

    onDestroy(() => {
      clearInterval(interval);
    });

    return { count };
  }
}

Provided lifecycle:

  • onInit
  • onDestroy
  • onChanges
  • onDoCheck
  • onAfterContentInit
  • onAfterContentChecked
  • onAfterViewInit
  • onAfterViewChecked

Note: Custom lifecycle can be created via composeLifecycle here

ref

ref() is to creating a reactive state

import { ref } from 'ngx-hooks';

class AppComponent {
  static ngHooks(context: NgHooksContext<AppComponent>) {
    const title = ref('Angular');

    setTimeout(() => {
      title.value = 'Angular Function API';
    }, 3000);

    return { title };
  }
}

computed

computed takes a getter function in first argument and returns a computed reactive value based on a getter function.

import { computed, ref } from 'ngx-hooks';

class AppComponent {
  static ngHooks(context: NgHooksContext<AppComponent>) {
    const count = ref(0);
    const double = computed(() => count.value * 2);

    setInterval(() => {
      count.value++;
    }, 1000);

    return { double };
  }
}

it does also take second argument as setter which will be invoked when computed reactive value is set.

import { computed, ref } from 'ngx-hooks';

class AppComponent {
  static ngHooks(context: NgHooksContext<AppComponent>) {
    const count = ref(0);
    const double = computed(() => count.value * 2, (double) => (count.value = double / 2));

    double.value = 1000;

    return { double };
  }
}

Note: assigning to a computed value will not have any effect if setter is not provided

observe

observe returns a reactive value by observing a property of any object.

import { observe, computed } from 'ngx-hooks';

class AppComponent {
  static ngHooks(context: NgHooksContext<AppComponent>) {
    const id = observe(context, (context) => context.id);
    const currentUser = computed(() => USERS.find((user) => user.id === id.value));

    return { currentUser };
  }
}

watch

It runs a watcher function when ever dependency or dependencies change. Dependency can be a reactive value or a getter function.

import { watch, observe, ref } from 'ngx-hooks';

class AppComponent {
  static ngHooks(context: NgHooksContext<AppComponent>) {
    const id = observe(context, (context) => context.id);
    const user = ref(null);
    watch(id, async (newId, oldId, onCleanup) => {
      const result = await fetch('some.domain.url/api/user/' + newId);
      const data = await result.json();
      user.value = data;

      onCleanup(() => {
        // cleanup functionality
      });
    });

    return { user };
  }
}
  • Watching multiple sources

import { watch, observe } from 'ngx-hooks';

class AppComponent {
  static ngHooks(context: NgHooksContext<AppComponent>) {
    const id = observe(context, (context) => context.id);
    const params = observe(context, (context) => context.params);
    watch([id, () => params.value.user_role], ([newId, newUserRole], [oldId, oldUserRole], onCleanup) => {
      // ...
      onCleanup(() => {
        // cleanup functionality
      });
    });

    // ...
  }
}

Options

watch takes options object (optional) in last function parameter.

watch(
  id,
  () => {
    // call immediately when id changes and will not call immediately
  },
  { mode: 'sync', lazy: true }
);
  • Watch mode:

    By default, it flushes after content checked. this behaviour can be changed via mode option.

    • sync: flushes synchronously
    • content: flushes after content checked (default)
    • view: flushes after view checked
  • Lazy Watch:

    When lazy is true, watcher function will not run immediately. (default is false)

Note: watch fallbacks to sync mode if it is used in createProvider.

inject

inject is same as Angular's Injector.get.

import { inject } from 'ngx-hooks';

class AppComponent {
  static ngHooks(context: NgHooksContext<AppComponent>) {
    const store = inject(Store);

    // do anything with store
  }
}

createProvider

createProvider creates provider which can be injected in components, directives or providers. the return value must be an object.

import { createProvider, inject } from 'ngx-hooks';

const [LogService, LogServiceProvider] = createProvider('LogService', () => {
  function log(...args) {
    console.log('Log:', ...args);
  }
  return { log };
});

@Component({
  // ...
  providers: [LogServiceProvider],
})
@FunctionComponent()
class AppComponent {
  static ngHooks(context: NgHooksContext<AppComponent>) {
    const logService = inject(LogService);

    logService.log('log some useful stuff');
  }
}
  • Usage with object destructuring:

    import { createProvider } from 'ngx-hooks';
    
    const { token: LogService, provider: LogServiceProvider } = createProvider('LogService', () => {
      // ...
    });
  • Usage with providedIn:

    providedIn is root by default

    import { createProvider } from 'ngx-hooks';
    
    const { token: LogService, provider: LogServiceProvider } = createProvider('LogService', {
      providedIn: AppModule,
      factory: () => {
        // ...
      },
    });

Note: In provider, only onDestroy lifecycle can be used other lifecycle will have no effects.

Helpers

  • composeLifecycle

    it can be use to compose custom lifecycle which give can be used in composed functions as well.

    import { composeLifecycle } from 'ngx-hooks';
    
    const onWriteValue = composeLifecycle<(value: string) => void>('writeValue');
    
    @Component({
      // ...
    })
    @FunctionComponent({
      lifecycle: [onWriteValue],
    })
    class AppComponent {
      static ngHooks(context: NgHooksContext<AppComponent>) {
        onWriteValue((value) => {
          // do something with value
        });
      }
    }
  • fromRef

    it can be used to un-wrap ref or Object/Array of refs deeply

    import { fromRef, ref } from 'ngx-hooks';
    
    const id = ref('001');
    fromRef(id); // '001'
    
    const refsArray = [ref(1), ref(2)];
    fromRef(refsArray); // [1, 2];
    
    const refMap = {
      ref1: ref('value1'),
      deep: {
        nestedRef: ref('value2'),
      },
    };
    fromRef(refMap); // {ref1: 'value1', deep: {nestedRef: 'value2'}}

FAQs

  • Why ngHooks method is static method?

    To avoid confusion of this keyword as we restricted the usage of it.

    As we don't allow to use this in ngHooks function but if it would be a class method then this should be referenced to class instance as per semantic of Javascript.

LICENSE

MIT