Git Product home page Git Product logo

ember-stickler's Introduction

NPM Version NPM Downloads NPM License Travis Build Status Code Climate Code Climate Coverage

Ember Stickler

Component based validations for ember

Install with:

ember install ember-stickler

ember-stickler is comprised of two components validated-form and validation-wrapper. The validation-wrappers wrap around each input and are nested inside a validated-form.

  {{#validated-form}}
    {{#validation-wrapper}}
      <input type='text' value={{value}}/>
    {{/validation-wrapper}}
  {{/validated-form}}

Validated Form

  {{#validated-form as |register submit reset submitErrors formState|}}

  {{/validated-form}}

validated-form submits by calling sendAction on whatever action attr you add and will default to submit. It invokes the action passing the following arguments reset, resolve, reject.

The validated-form yields the following:

  1. register, this is used by the validation-wrappers to register themselves with the form.

  2. submit this will trigger the validations in each of the validation-wrappers and will submit if they all pass.

  3. reset sets all the validation state and errors back to their initial state and changes the form state from pending to resolved and reject takes an error object with keys being the name of the field and value an array of error message strings.

  4. formState an object with the following properties:

  • isDefault
  • isPending
  • isResolved
  • text // default, pending, resolved, rejected.
  • disabled // will be false when valid or is disableDuringSubmit attr is added to the validated-form and the submit is pending.

All this allows you to do something like this in your route:

actions: {
  submit(reset, resolve, reject) {
    const self = this;
    self.get('service').submit({
      firstName: self.controller.get('firstName'),
      lastName: self.controller.get('lastName'),
      age: self.controller.get('age'),
    })
    .then(function() {
      reset();
      resolve();
    })
    .catch(function(errors) {
      reject({
        firstName: errors.firstName, //['first name is invalid!']
        lastName: errors.lastName,
        age: errors.age,
      });
    });
  }
}

Errors are then yielded by the validated-form and passed to each of the individual validation-wrappers.

  {{#validated-form as |register submit reset submitErrors formState|}}
    {{#validation-wrapper register=register submitErrors=submitErrors.firstName}}
      <input type='text' value={{firstName}}/>
    {{/validation-wrapper}}
  {{/validated-form}}

Validation Wrapper

Validation rules are added to the validation-wrappers with a rules attribute rules='' (separated by spaces). Messages and other defaults can be overridden with additional camelCased attributes formatted like <validation-name><option>.

  {{#validated-form as |register submit reset submitErrors formState|}}
    {{#validation-wrapper
      register=register
      submitErrors=submitErrors.firstName
      rules='required min-length'
      minLengthValue=5
      minLengthMessage='a minimum of 5 characters is required'
      as |checkForValid validate errors validationState|
    }}
    <input
      type='text'
      value={{firstName}}
      onblur={{action checkForValid value="target.checked"}}/>
      onchange={{action validate value="target.checked"}}/>
    {{/validation-wrapper}}
  {{/validated-form}}

The validated-wrapper yields the following:

  1. checkForValid an action which will ignore errors and only change the state when it passes the validation.

  2. validate which will check for both success and errors.

  3. errors an array of error messages.

  4. validationState object with the following properties:

  • valid // null, true, false
  • isValid // true, false
  • isInvalid // true, false
  • isInitial // true, false
  • text // valid, invalid, initial

Helpers

stickler provides class-state helper for managing error classes it takes valid as the first param and then three classes first for true, the second for false and the third for null, the third param defaults to an empty string.

  <div class="form-group {{class-state validationState.valid 'has-success' 'has-error'}}">

stickler also provides a first helper which you can use to get the first error message from errors

{{#if errors}}
  <span>{{first errors}}</span>
{{/if}}

Validations

Email

Rule: email

Attrs: emailMessage

Required

Rule: required

Attrs: emailMessage

Min Length

Rule: min-length

Attrs: minLengthMessage, minLength

Max Length

Rule: max-length

Attrs: maxLengthMessage, maxLength

Exists

Rule: exists

Attrs: existsMessage

Url

Rule: url

Attrs: urlMessage

Digits

Rule: digits

Attrs: digitsMessage

Number

Rule: number

Attrs: numberMessage

Date

Rule: date

Attrs: dateMessage

DateISO

Rule: dateISO

Attrs: dateISOMessage

Credit Card

Rule: credit-card

Attrs: creditCardMessage

Max

Rule: max

Attrs: maxMessage

Min

Rule: min

Attrs: minMessage

Format

Rule: format

Attrs: formatMessage, format

Transforms

  • trim
  • digit

You can add more rules/transforms by creating a app/validations directory and adding a file in the following formats:

For Validations:

import Validation from 'ember-stickler/validation';
export default {
  validate(value, errors) {
    // add rule logic here
    // push message to errors
    // return errors
  }
}

For Transforms:

import Transform from 'ember-stickler/transform';

export default Transform.create({
  transform(value) {
    // add transform logic here
    // return new value
  }
});

The this context in all the rules will be the component that the rule is validating allowing access to the value const value = this.get('value'); as well as any other attrs const value = this.get('minLengthMessage');.

Full Example

<div class='container'>
  <h2>Test Form</h2>

 {{#validated-form as |register submit reset submitErrors formState| }}

   {{#validation-wrapper
    class="input-group"
    register=register
    rules="exists is-eleven"
    submitErrors=submitErrors.intensity
    as |checkForValid validate errors validationState| }}

       <label for="intensity">Department To Route Campaign Responses To</label>
       <input type="range" id="intensity" value={{intensity}} min=0 max=11 oninput={{action validate value="target.value"}}>

     {{#if errors}}
         <div class="col-xs-12 text-small text-danger">{{first errors}}</div>
     {{/if}}

   {{/validation-wrapper}}


   {{#validation-wrapper
    class="input-group"
    register=register
    rules="exists"
    submitErrors=submitErrors.isIntense
    as |checkForValid validate errors validationState| }}

       <label for="checkbox-intensity">Department To Route Campaign Responses To</label>
       <input type="checkbox" id="checkbox-intensity" value={{isIntense}} onchange={{action validate value="target.checked"}} >

     {{#if errors}}
         <div class="col-xs-12 text-small text-danger">{{first errors}}</div>
     {{/if}}

   {{/validation-wrapper}}


   {{#validation-wrapper
    class="input-group"
    register=register
    rules="exists is-eleven"
    submitErrors=submitErrors.coolness
    as |checkForValid validate errors validationState| }}

       <label for="intensity">Department To Route Campaign Responses To</label>
       <select onchange={{action validate value="target.value"}}>
         {{#each choices key="@identity" as |choice|}}
             <option value={{choice}} selected={{is-equal coolness choice}}>{{choice}}</option>
         {{/each}}
       </select>

     {{#if errors}}
         <div class="col-xs-12 text-small text-danger">{{first errors}}</div>
     {{/if}}

   {{/validation-wrapper}}

   {{#validation-wrapper
    class="input-group"
    register=register
    rules='trim required min-length' minLengthValue='3'
    submitErrors=submitErrors.firstName
    as |checkForValid validate errors validationState| }}

      <div class="form-group {{class-state validationState.valid 'has-success' 'has-error'}}">
        <label for='firstName'>First Name</label>

        <input
          type="text"
          class='form-control'
          id='firstName'
          placeholder='first name'
          value={{firstName}}
          onblur={{ action (action validate) value='target.value' }}
          oninput={{ action (action checkForValid) value='target.value' }}>

        {{#if errors}}
          <span>{{first errors}}</span>
        {{/if}}
      </div>

   {{/validation-wrapper}}

   {{#validation-wrapper
    class="input-group"
    register=register
    rules='required max-length' maxLengthValue='3'
    submitErrors=submitErrors.lastName
    as |checkForValid validate errors validationState| }}

      <div class="form-group {{class-state validationState.valid 'has-success' 'has-error'}}">
        <label for='lastName'>Last Name</label>
        <input
          type="text"
          class='form-control'
          id='lastName'
          placeholder='last name'
          value={{lastName}}
          onblur={{ action (action validate) value='target.value' }}
          oninput={{ action (action checkForValid) value='target.value' }}>

        {{#if errors}}
          <span>{{first errors}}</span>
        {{/if}}
      </div>

   {{/validation-wrapper}}


   {{#validation-wrapper
    class="input-group"
    register=register
    rules='required email'
    submitErrors=submitErrors.email
    as |checkForValid validate errors validationState| }}

      <div class="form-group {{class-state validationState.valid 'has-success' 'has-error'}}">
        <label for='email'>Email</label>
        <input
          type="text"
          class='form-control'
          id='email'
          placeholder='email'
          value={{email}}
          onblur={{ action (action validate) value='target.value' }}
          oninput={{ action (action checkForValid) value='target.value' }}>

        {{#if errors}}
          <span>{{first errors}}</span>
        {{/if}}
      </div>

   {{/validation-wrapper}}
    <p>
      <button class='btn btn-primary' disabled={{formState.disabled}} {{action submit}}>Submit</button>
    </p>

 {{/validated-form}}

</div>

Authors

License

The MIT License

Copyright (c) 2015 sethpollack, runspired

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

ember-stickler's People

Contributors

sethpollack avatar runspired avatar waffle-iron avatar ember-tomster avatar

Watchers

greyhwndz avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.