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 🙏

© 2024 – Pkg Stats / Ryan Hefner

ionform

v0.0.28

Published

a dynamic form generator and validator

Downloads

56

Readme

IonForm a super lightwieght form component Readme 📝

This package is under development the api is likely to change. Stable releases will start with versions equal to or greater than 1. A working demo is running in index.html

Get Started 🚀

Use the custom ion-form tag anywhere in your code. Make sure to give your form a unique name.

 
 <ion-form formname="myForm"></ion-form>

Prebuilt Components/Templates/Form 🔥

Everything works out of the box. No configuration required.✨

Import the package into your Vanilla, Angular, React, or Vue Framework.

in your tsConfig set 'allowSyntheticDefaultImports' to true, this is for password-validator "allowSyntheticDefaultImports": true,


import { IonForm} from 'ion-forms';

const myForm = IonForm('myForm');

const stringKeyValuePairs: StringDictionary 

    =  {
    
    "name": 'mazda',
    
    "color": 'purple' 
    
     };

myForm.createForm({ 
    
    jsonForm: stringKeyValuePairs
    
     });

Once you're done, that's it.

Your field validation is a simple callback that takes the name of your input. 🏈.

The callback provides you a fieldState 🤯

The fieldState provides you 💡

An updated value of your input ✔️
An helper html element ✔️
An error html element ✔️
The current state of each input ✔️
An allValid boolean ✔️
Validator methods ✔️
A lnkField method for dependent adjacent field values ✔️

🚦The fieldValidate function must return a boolean

 const stringKeyValuePairs: StringDictionary = 

    { 

    "password": 'mypassword',

     "repeatPassword": ''

    };

myForm.createForm({ jsonForm: stringKeyValuePairs });
   
myForm.fieldValidate('repeatPassword', async (fieldState: FieldValidationResponse): Promise<boolean> => {

      const { value, validator, helper, error, linkField }:{
          value: string;

          validator: any;

          helper?: HTMLIonNoteElement;

          error?: HTMLIonNoteElement;

         linkField?: (name: string) => string | null; } = fieldState;

      if (linkField) {

        const link = linkField('password');

        if (link === value) {

          fieldState.helper.innerText = 'do your thing bro!';

          if (fieldState.value.length > 3) {

            return true;

          }

          fieldState.error.innerText = 'get your password right, you bad password typier!';

          return false;

        }

      }
      return false;
    });

field validation with dynamic helper and error messages


 myForm.fieldValidate('name', async (fieldState: HTMLIonInputElement |  FieldValidationResponse): Promise<boolean> =>  {

      const { 
          
          value, 
          
          validator, 
          
          helper,
          
          error, 
          
          linkField 
          
          } :
            { 
        value: string; 
         
         validator: any;
         
         helper?: HTMLIonNoteElement;
         
         error?: HTMLIonNoteElement;
         
         (fieldName: string) => string; 
         
            } = fieldState;

      if (validator.isEmail(value)) {

        helper.textContent = 'congrats! your email is now correct';

        return true;

      }

      error.textContent = 'it needs to be an email my friend';
      
      return false;

    });

entire form validation

on valid form changes, the values appear on onFormChange

no updates are propagated on pristine or invalid values

If a form contains the original values after having been dirtied, the from is reset to its pristine state and no form change is triggered for that input.


  myForm.onFormChange((formChange: ValidFormResponse): boolean => {
    
    const {changes, event, completeForm, 
    
    states, allValid}: {changes: Map<string, string>;
    
    event: Event;
    
    completeForm: Map<string, string>;
    
    states: Map<string, boolean>;
    
    allValid: boolean;} = formChange;
    
    if(allValid)

    {
    
    // do something;
    
        return true;
    
    }

      return false;
    
    });

generate the HTML schema.

limitations

Where Buttons are nesseary, only one button per form.


const detailedSchema = [

  {name:'first',value:'none',disabled: 'true', type: 'text', tagName: 'input' },

  {name:'last', value:'', disabled: 'true', type: 'text', tagName: 'input' },

  {name:'email', value:'', disabled: 'true', type: 'text', tagName: 'input' },

  {name:'phone', value:'',  disabled: 'true', type: 'text', tagName: 'input' },

  {name:'postcode', value:'', disabled: 'false', type: 'text', tagName: 'input' },

  { name:'housenumber', value:'' disabled: 'false', type: 'text', tagName: 'ion-input' },

  { name:'age', value:'', disabled: 'false', type: 'text', tagName: 'ion-input' },

  {name:'submit',  disabled: 'false', type: 'button', tagName: 'ion-button' }

]

conversely you can specify your validator function in your schemaDictionary

make sure to check the fieldState options to see if they are available.


const schemaDictionary = {

        first:

          { disabled: 'true', type: 'text', tagName: 'input', validator: function(fieldState: HTMLIonInputElement |  FieldValidationResponse) {

            const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
            if(helper){


              return true
            }

            return false;
            
                }
          }
    }

Use your favorite validation tools 🧑‍🔧, and get that validation satisfaction! 😌

validator.js 💣

password-validator 💣

define a custom validation schema 🏗

Check the fieldState hooks/options to see if they are available 🪝


const validationSchema = {

    first: async (fieldState: HTMLIonInputElement |  FieldValidationResponse): Promise<boolean> => {
    
        const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
            
        if(value){
            
            const first: string = value;
            
            return first.length > 2 && first.length < 20;
        
        }

         return false;
    },

    username:
     
     async (fieldState: HTMLIonInputElement |  FieldValidationResponse): Promise<boolean> => {
    
        const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
       
        const first: string = value;
       
        return first.length > 2 && first.length < 20;
    },

    last: (fieldState: HTMLIonInputElement |  FieldValidationResponse): boolean => {
        
        const { value, validator, passwordValidator, helper, error, linkField } = fieldState;

        const last: string = fieldValue.value;
        
        return last.length > 2 && last.length < 20;

    },

    email: (fieldState: HTMLIonInputElement |  FieldValidationResponse): boolean => {
        
        const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
        
        const email: string = value;
        
        return validator.isEmail(email);

    },

    age: (fieldState: HTMLIonInputElement |  FieldValidationResponse): boolean => {
      
      const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
      
      const age: number = +value;
    
      return age >= 18;
    },

    postcode: (fieldState: HTMLIonInputElement |  FieldValidationResponse): boolean => {
      
       const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
      
        const zip: string = value;
      
        const validZipTest = /(^\d{5}$)|(^\d{5}-\d{4}$)/;
      
        return validZipTest.test(zip);
    },

    state: (fieldState: HTMLIonInputElement |  FieldValidationResponse): boolean => {
      
        const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
      
        const state: string = value;
      
        return state.length > 1;
    },

    city: (fieldState: HTMLIonInputElement |  FieldValidationResponse): boolean => {
        
        const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
        
        const city = value;
        
        const rgx = /(^[a-zA-Z',.\s-]{1,25}$)/;
        
        return rgx.test(city);

    },

    housenumber: (fieldState: HTMLIonInputElement |  FieldValidationResponse): boolean => {
    
        const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
    
        const nums = value;
    
        return nums.length && !isNaN(+nums);

    },
    
    password: (fieldState: HTMLIonInputElement |  FieldValidationResponse): boolean => {
        
        const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
        
        const password = fieldValue.value;
        
        if(passwordValidator){
        
            const schema = new passwordValidator();
        
            schema
            .is().min(8)                                    // Minimum length 8
            .is().max(100)                                  // Maximum length 100
            .has().uppercase()                              // Must have uppercase letters
            .has().lowercase()                              // Must have lowercase letters
            .has().digits(2)                                // Must have at least 2 digits
            .has().not().spaces()                           // Should not have spaces
            .is().not().oneOf(['Passw0rd', 'Password123']);
        
            return schema.validate(password)
        
            }

        return false;
      
      },

    upc: (fieldState: HTMLIonInputElement |  FieldValidationResponse): boolean => {
     
        const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
        
        return validateUPC(value);
    },

    repeatpassword: (fieldState: HTMLIonInputElement |  FieldValidationResponse): boolean => {
    
        const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
    
        const repeatedValue = value;
        
        const originalValue = fieldValue.shadowRoot.querySelector('[name="password"]')

        return originalValue === repeatedValue;
    },

    phone: async (fieldState: HTMLIonInputElement |  FieldValidationResponse): Promise<boolean> => {
       
       const { value, validator, passwordValidator, helper, error, linkField } = fieldState;
       
        const phone = value;
       
        return validator.isMobilePhone(phone, 'en-US');
    
    },

};

 const detailedSchema = [

        { name: 'first', value: 'Pillsbury', type: 'text', tagName: 'input', validator: validationSchema.first },


        { name: 'last', value: 'Doughboy', disabled: 'true', type: 'text', tagName: 'input', helper: 'enter your last name', validator: validationSchema.last },


        { name: 'email', value: '[email protected]', disabled: 'false', type: 'text', helper: 'enter your email', tagName: 'input', validator: validationSchema.email },


        { name: 'phone', value: '9494548213', disabled: 'true', type: 'text', tagName: 'input', validator: validationSchema.phone },


        { name: 'age', value: '55', disabled: 'false', type: 'text', tagName: 'ion-input', validator: validationSchema.age },


        { name: 'postcode', value: '', disabled: 'false', type: 'text', tagName: 'input', validator: validationSchema.name },


        { name: 'city', disabled: 'false', type: 'text', tagName: 'ion-input', value: 'city', validator: validationSchema.city }

      ];

      form2.createForm({ detailedSchema: detailedSchema })