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

observable-forms

v2.0.6

Published

Observables and static type checking for all kind of forms.

Downloads

20

Readme

  Observable Forms npm version

     Framework-agnostic port of Angular's Reactive forms.

Version 2

Removed jQuery dependency. Added support for native HTMLElement and NodeList.

Introduction

A client-side library for creating an observable object from HTML form elements. As an observable object, it will have built-in reactivity so the library is framework-agnostic and compatible with any ecosystem. It can be used with MVC, SPA, SSR, etc., frameworks. Reactivity is RxJS based and its API is inspired by what Angular has used for forms since Angular 2.

Functionality & Usage

Form Control

This is one of the two fundamental building blocks of Observable Forms, along with FormGroup. It tracks the value and validation status of an individual form control (a single text input, a set of radio inputs with the same name, etc.).

Example of creating and using a form control:

// Module imports
import ...

// Example 1: logging FormControl values
let firstName = document.getElementById('firstName').asFormControl().enableValidation();
firstName.valueChanges.subscribe(value => console.log('My new value is: ' + value));

// Example 2: Complex directing between different controls
// Using delivery and payment controls
let deliveryAddress = document.getElementById('delivery-address').asFormControl();
let paymentAddress = document.getElementById('payment-address').asFormControl().enableValidation();

// Check if they should be the same 
let areAddressesDifferent$ = document.getElementById('different-checkbox').asFormControl().valueChanges
    .pipe(map(value => value === 'true'), startWith(false));

// And either validate payment address if different, or use value of delivery address
areAddressesDifferent$.pipe(switchMap(value => value
    ? paymentAddress.statusChanges.pipe(tap(status => status === FormControlStatus.INVALID && alert('Entered address is not valid')))
    : deliveryAddress.valueChanges.pipe(tap(value => paymentAddress.setValue(value)))
)).subscribe();

Form Group

Form group aggregates controls found in the subtree of the selected element(s) into one object, with each control's name as the key. Name is either control's name attribute or one manually provided. Class of this object accepts a type parameter representing the model of the form group, which provides static type checking when working with the controls and values. Type checking is also available in plain JavaScript no-build projects using JSDoc (demo available).

Some features of the FormGroup objects are:

  • The value is a JSON object of child controls' names and values.
  • Controls can be added and removed from the group.
  • Validation
  • Custom controls as child controls
  • Simple abstraction for radio and checkbox controls
  • Web Components support
class MyForm {
    fullName: string;
    isSubscriber: boolean;
    addresses: {street: string; city: string}[];
}

// Create a form group (TS version)
let form = document.querySelector('form').asFormGroup<MyForm>();

// Accessing child controls and value, with editor providing type information
form.controls.fullName.valueChanges.subscribe(_ => '...')
form.controls.addresses[0].city.valueChanges.subscribe(_ => '...');
console.log(form.value.isSubscriber);

Some of the properties, observables and methods of FormControl and FormGroup are:

  • value, valueChanges   - string or JSON
  • status, statusChanges - valid, invalid or disabled
  • touched       - has the user interacted with the element(s) at all
  • dirty          - has the user changed element(s) value
  • setValue()
  • reset()

Despite some inconsistencies, Angular docs can be used as more detailed API reference: AbstractControl, FormControl, FormGroup.

Demos

These demos will try to cover as many scenarios as possible, such as:

  • disabling / enabling form controls
  • adding / removing controls from the DOM
  • changing element's types
  • creating controls from non-input elements
  • handling Web Components
  • changing form's data / resetting
  • handling arrays

Demo 1 - "A standard form"

A JavaScript project covering a lot of library's functionalities, and showing how to integrate type checking into JavaScript code. Demo 1

Note: that CodeSandbox has some built-in js bundler that allows non-standard imports in .js files. Below those imports are comments on how they should be used plain .js files.

Demo 2 - "Custom made"

A TypeScript project covering custom form controls. Also demonstrates support for Web Components. Demo 2

Demo 3 - "Form update"

A JavaScript project showing how to change form's data and how to reset it. Demo 3

Installation

ES6 via npm

npm i observable-forms Inside a html script tag, or in javascript:

<script type="module">
    import {} from "./node_modules/observable-forms/dist/index.js";
    // Library self initializes when module is loaded.

    let formControl = document.querySelector('input').asFormControl().valueChanges.subscribe(val => console.log(val));
    ...
</script>

or, in Typescript:

import {ConfigService, Validators} from "observable-forms";

// Declaratively adding validation to controls using html attributes
ConfigService.registerAttributeValidators({
    'data-val-required': Validators.required,
    'data-val-email': Validators.email,
    'data-val-url': c => c.value === '' || URL_REGEXP.test(c.value) ? null : {url: true}
});

CDN

For CDN, you can use unpkg: https://unpkg.com/observable-forms/dist/index.js

<script type="module">
    import {} from "https://unpkg.com/observable-forms/dist/index.js";
    ...
</script>