Skip to content

Handlebar helpers for twoway binding templates to collection

Notifications You must be signed in to change notification settings

OTAperu/Meteor-handlebar-bind

Repository files navigation

#Handlebar-bind - This is early sneak peek test state! Is a simple way of binding Collections to the Meteor handlebars template environment.

Have a look at Live example

There are 3 simple bind handlers

  • {{bind}}
  • {{bindAction}}
  • {{bindSelected}}

And 2 for validation feedback:

  • {{bindStatus}}
  • {{bindStatusReport}}

##How to use?

####1. Install:

    mrt add handlebar-bind

Requires Meteorite get it at atmosphere.meteor.com

###Binding Template to Collection :

  var Contacts = new Meteor.Collection('contacts');
  Contacts.bindTemplate('hello');

It's only possible to bind a template once, binding it multiple times will throw an error

###Using {{bind 'key'}} helper: This helper sets an properties id, bindKey and value for the tag <input> * at the moment this is the only input supported* Here's an example using the {{find}} from the handlebar-helpers package:

  {{#each find 'Contacts' '{}'}}
    <input {{bind 'name'}}/><br/>
  {{/each}}

To make this a simple live / twoway binding set option liveUpdate:true eg.: Contacts.bindTemplate('hello', { liveUpdate: true });

###Using {{bindAction 'Action'}} helper: This helper lets you define tags: <a class="btn">, <button> and <input> as an binding for actions: create, update, delete, upload and cancel - last one resets the form fields to default cancel doesn't work when liveUpdate:true as this updates database live on keystrokes

Note: At the moment the upload saves file in suffix _data eg.

<input type="file" {{bindAction 'upload' 'image'}}/>
<img src="{{image_data}}"  {{bind 'image_data'}}/>

The fileupload part is still not working as expected due to spark preserve and live update

  {{#each find 'Contacts' '{}'}}
    <input {{bind 'name'}}/>
    <button {{bindAction 'update'}}>Update</button>
    <a {{bindAction 'cancel'}} class="btn">Cancel</a>
    <input type="button" value="Delete" {{bindAction 'delete'}}/>
    <br/>
  {{/each}}

This will list existing contacts names for optional update and delete actions. If one wants to add a contact this can be done by adding bindings outside the data iteration. Example:

  Add contact:<br/>
  <input {{bind 'name'}}/>
  <button {{bindAction 'create'}}>Add</button>
  <button {{bindAction 'cancel'}}>Cancel</button>
  Existing contacts:<br/>
  {{#each find 'Contacts' '{}'}}
    <input {{bind 'name'}}/>
    <button {{bindAction 'update'}}>Update</button>
    <a {{bindAction 'cancel'}} class="btn">Cancel</a>
    <input type="button" value="Delete" {{bindAction 'delete'}}/>
    <br/>
  {{/each}}

This way input forms can be used for modal views, and in multiple templates - since multiple templates can be binded to a single Collection.

###Validation using {{bindStatus 'templateName'}}: Validation using handlebar-bind is a bit more complicated and needs to be set up before working. I've only made a couple validators so far, but if you want to share a validation function your wellcome. I would add it to the Validators object

####There are three types of data validation:

  • Dirty data - this is when data in formula and database dont match
  • Required data - data not filled in but is required
  • Invalid data - Custom validation failure, a validator allows '' but validates the given value and returns false - the data is invalid

####Setting client side validation:

      var Contacts = new Meteor.Collection('contacts');
      Contacts.bindTemplate('hello', {
      liveUpdate: false,  //Set true if should be live update, if false then collective update eg. via bindAction
      validation: {
        email: {
          validators: [ Validators.email ] //Supports multiple validators
        }
      }
    });

The data binding for 'email' in Contacts Collection and Template 'hello' is validated against Validators.email function - Note that an empty string '' is accepted.

Validations are weigthed in the sense of three levels of acceptance:

  • 0 - Success - if value is valid
  • 1 - Warning - if a not required field is invalid
  • 2 - Error - if a required field is invalid

All of the validations and dirty data marks are kept in a bindRecord object. The bindRecord is a reactive data source - giving instant live validation updates in the templating system.

###Validation data from the bindRecord can be used in four levels:

  • Attribute level - only one attribute eg. dirty from a key email gets returned
  • Key level - only validation data from a single field
  • Record level - only validation data from one data context
  • Template level - contains keys attributes counts eg. how many fields have error on email

####Attribute level - Using the {{bindStatus 'templateName' 'key' 'attribute'}} This helper returns a boolean true/false value from a key attribute (success, warning, error, dirty)

Example:

  Add contact:<br/>
  <input {{bind 'name'}}/>
  <input {{bind 'email'}}/>
  {{#if bindStatus 'hello' 'email' 'invalid'}}*{{/if}}
  {{#if bindStatus 'hello' 'email' 'required'}}*{{/if}}
  {{#if bindStatus 'hello' 'email' 'dirty'}}*{{/if}}
  {{#if bindStatus 'hello' 'email' 'warning'}}?{{/if}}
  {{#if bindStatus 'hello' 'email' 'error'}}!{{/if}}

####Key level - Using the {{bindStatus 'templateName' 'key'}} This helper returns the bindRecord at key level. Returned object structure:

{
    invalid: true/false,
    success: true/false,
    warning: true/false,
    error: true/false,
    dirty: true/false
}

Example:

  Add contact:<br/>
  <input {{bind 'name'}}/>
  <input {{bind 'email'}}/>
  {{#with bindStatus 'hello' 'email'}}
    {{#if dirty}}*{{/if}}
    {{#if error}}!{{/if}}
  {{/with}}
  <button {{bindAction 'create'}}>Add</button>
  <button {{bindAction 'cancel'}}>Cancel</button>
  Existing contacts:<br/>
  {{#each find 'Contacts' '{}'}}
    <input {{bind 'name'}}/>
    <input {{bind 'email'}}/>
    <button {{bindAction 'update'}}>Update</button>
    <a {{bindAction 'cancel'}} class="btn">Cancel</a>
    <input type="button" value="Delete" {{bindAction 'delete'}}/>
    <br/>
  {{/each}}

####Record level - Using the {{bindStatus 'templateName'}} This helper returns the bindRecord at record level. Returned object structure:

name : '',
keys [
    name: {
        warning: true/false,
        error: true/false,
        dirty: true/false,
        invalid: true/false,
        required: true/false
    },
    email: {
        warning: true/false,
        error: true/false,
        dirty: true/false,
        invalid: true/false,
        required: true/false
    }
]

####Template level - Using the {{bindStatusReport 'templateName'}} This helper returns the bindRecord at template level. Returned object structure: [key]{attribute} containing counts.

[ //Firs item is a total stats of template validation
  total: {
      warning: 0 .. ?, //All warnings counted
      error: 0 .. ?,
      dirty: 0 .. ?,
      invalid: 0 .. ?,
      required: 0 .. ?
  }
], [ //Pr. Key follows as totals from the template validation
  name: '',
  key: {
      warning: 0 .. ?, //num of wrnings for single key in template
      error: 0 .. ?,
      dirty: 0 .. ?,
      invalid: 0 .. ?,
      required: 0 .. ?
  }
]

About

Handlebar helpers for twoway binding templates to collection

Resources

Stars

Watchers

Forks

Packages

No packages published