Skip to content

Instantly share code, notes, and snippets.

@mcoetzee
Created July 30, 2016 12:48
Show Gist options
  • Save mcoetzee/abdc7d66eee1b1c636101eef110fbb05 to your computer and use it in GitHub Desktop.
Save mcoetzee/abdc7d66eee1b1c636101eef110fbb05 to your computer and use it in GitHub Desktop.

Create form validators from basic definitions.

const paymentDef = {
  validates: {
    currency: ['isRequired'],
    amount: ['isRequired', 'isNumeric'],
    reference: [
      'isRequired',
      { validator: 'isReferency', message: "This must be in format: '0123/4567'" },
    ],      
  },

  // Custom validator
  isReferency(reference) {
    return !!reference.match(/^\d{4}\/\d{4}$/);
  },
};

const validatePayment = createValidator(paymentDef);

A validated form includes messages and a valid flag.

const result = validatePayment({
  currency: 'EUR',
  amount: 'foo',
  reference: '0012/003',
});

console.log(result);
// >_ {
// >_   currency: 'EUR',
// >_   amount: 'foo',
// >_   reference: '0012/003',
// >_   messages: {
// >_     amount: 'This must be a number',
// >_     reference: "This must be in format: '0123/4567''',
// >_   },
// >_   valid: false,
// >_ }

Nested forms

Definitions can be embedded within other definitions (formception).

const fooDef = {
  validates: {
    fooFieldA: ['isRequired', 'isNumeric'],

    @nested // This is a nested definition (can be extracted and used on its own)
    bars: {
      validates: {
        barFieldA: ['isRequired'],
        barFieldB: [{ validator: 'isBarLike', message: 'This isn\'t very bar-like' }],
      },
     
      isBarLike(barFieldB) {
        return barFieldB === 42;
      },
    }
  }
};

const validateFoo = createValidator(fooDef);

const result = validateFoo({
  fooFieldA: 21,
  bars: [
    { barFieldA: 'Cats', barFieldB: 42 },
    { barFieldA: 'Dogs', barFieldB: 21 },
  ]
});

console.log(result);
// >_ {
// >_   fooFieldA: 21,
// >_   bars: [
// >_     { 
// >_       barFieldA: 'Cats', 
// >_       barFieldB: 42, 
// >_       messages: {}, 
// >_       valid: true
// >_     },
// >_     { 
// >_       barFieldA: 'Dogs', 
// >_       barFieldB: 21, 
// >_       messages: {
// >_         barFieldB: 'This isn't very bar-like'
// >_       }, 
// >_       valid: false
// >_     },
// >_   ],
// >_   messages: {
// >_     bars: 'This is not valid',
// >_   },
// >_   valid: false,
// >_ }

Composed forms

Definitions can be merged into one.

const contactDef = {
  validates: {
    email: ['isEmail'],
    phone: ['isNumeric']
  }
};

const detailedPaymentDef = merge(
  paymentDef,
  contactDef
);

const validateDetailedPayment = createValidator(detailedPaymentDef);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment