dom-bindings

Takes binding declarations and returns key-tree-store of functions that can be used to apply those bindings.

dom-bindings

Takes binding declarations as described below and returns key-tree-store of functions that can be used to apply those bindings to a DOM tree.

The returned functions should be called with these arguments: The root element, the current value of the property, and a name for the binding types where that is relevant.

npm install dom-bindings

sets/maintains textContent of selected element. treats , null, and NaN as ''

'model.key': {
    type: 'text',
    selector: '.someSelector' // or role 
}

sets and maintains single class as string that matches value of property

  • handles removing previous class if there was one
  • treats , null, and NaN as '' (empty string).
'model.key': {
    type: 'class',
    selector: // or role 
}

sets the whole attribute to match value of property. treats , null, and NaN as '' (empty string).

'model.key': {
    type: 'attribute',
    selector: '#something', // or role 
    name: 'width'
}

add/removes class based on boolean interpretation of property name.

'model.active': {
    type: 'booleanClass',
    selector: '#something', // or role 
    // to specify name of class to toggle (if different than key name) 
    // you could either specify a name 
    name: 'active'
    // or a yes/no case 
    yes: 'active',
    no: 'not-active'
}

toggles whole attribute on the element (think checked) based on boolean interpretation of property name.

'model.isAwesome': {
    type: 'booleanAttribute',
    selector: '#something', // or role 
    name: 'checked'
}

toggles existance of entire element (uses a comment node as placeholder if gone) based on boolean interpretation of property name.

// simple show/hide of single element 
'model.key': {
    type: 'toggle',
    selector: '#something' // or role 
}
 
// show/hide where true/false show different things 
'model.key': {
    type: 'toggle',
    yes: '#true_case',
    no: '#false_case'
}

Toggles existance of multiple items based on value of property.

'model.activetab': {
    type: 'switch',
    cases: {
        'edit': '#edit_tab',
        'new': '#new_tab',
        'details': '#details_tab'
    }
}

If given an array, then treat each contained item as separate binding

'model.key': [
    {
        type: 'booleanClass',
        selector: '#something', // or role 
        name: 'active' // (optional) name of class to toggle if different than key name 
    },
    {
        type: 'attribute',
        selector: '#something', // or role 
        name: 'width'
    }
]

We've started using this convention a lot, rather than using classes and IDs in JS to select elements within a view, we use the role attribute. This lets designers edit templates without fear of breaking something by changing a class. It works wonderfully, but the only thing that sucks about that is the syntax of attribute selectors: [role=some-role] is a bit annoying to type a million types, and also in JS-land when coding and we see [ we always assume arrays.

I'm proposing that for each of these bindings you can either use selector or role, so these two would be equivalent:

'model.key': {
    selector: '[role=my-element]'
}
 
'model.key': {
    role: 'my-element'
}
 
'model.key': '#something' // creates `text` binding for that selector and property 
 
// `type` defaults to `text` so we can also do 
'model.key': {
    role: 'role-name'
}
var View = require('ampersand-view');
var templates = require('../templates');
 
 
module.exports = View.extend({
    template: templates.includes.app,
    bindings: {
        'model.client_name': {
            role: 'name'
        },
        'model.logo_uri': {
            type: 'attribute',
            name: 'src',
            role: 'icon'
        }
    }
});

Previously after having given views the ability to have their own properties (since view inherits from state) it was awkward to bind those to the DOM. Also, for binding things that were not just this.model the syntax had to change.

Now this is fairly simple/obvious:

module.exports = View.extend({
    template: templates.includes.app,
    props: {
        activetab: 'string',
        person: 'state',
        meeting: 'state'
    },
    bindings: {
        // for the property that's directly on the view 
        'activetab': {
            type: 'switch',
            case: {
                'edit': '#edit_tab',
                'new': '#new_tab',
                'details': '#details_tab'
            }
        },
        // this one is for one model 
        'person.full_name': '[role=name]',
        // this one is for another model 
        'meeting.subject': '[role=subject]'
    }
});

If you like this follow @HenrikJoreteg on twitter.

MIT