SkillAgentSearch skills...

Bindingjs

Separable, Reactive, Model-Agnostic View Data Binding for JavaScript

Install / Use

/learn @rummelj/Bindingjs
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

BindingJS -- Separable, Reactive, Model-Agnostic View Data Binding

BindingJS is a view data binding library for single page web applications. Another one? Yes! One that combines all the cool stuff, you may already know from other libraries like Knockout or AngularJS. BindingJS is not completely different, but has unique characteristics, that will convince you.

Separable
The binding is not mixed up with the HTML of the page, but defined in a separate place much like CSS. This makes it not only easier to understand and maintain, but also allows a more compact and powerful syntax. In addition, less code has to be repeated and the bad syntax highlighting in attribute strings is a thing of the past. You ever heard of Separation of Concerns? Here it is!

Reactive
BindingJS propagates changes of values and follows the idea of reactive programming. Your users will be thankful, if your web page immediately updates without a reload or any nasty wait times.

Model-Agnostic
Any access to the View Model or Presentation Model is made exclusively through a component called Adapter. This means, that BindingJS can be adapted to any kind of Model implementation such as JSON objects, Knockout Observables or Backbone Models by just exchanging a single component.

Have you ever noticed a web page flickering especially on a mobile device? This was probably caused by the binding library that changed more than necessary to render changes. BindingJS uses surgical updates taking care, that the modification of html is always minimal no matter if a list or an attributes is modified.

Getting Started

To start using BindingJS just download its latest version, which includes the library itself and a set of Model Adapters. If there is no Adapter for your Model yet, you can easily implement your own. After that, use the examples to get a first impression and to have a starting point for your experiments. To get the most out of BindingJS you need to learn how to interact with it through its API and what the syntax of its domain specific language is.

API

Here is a simple example, that two way binds the value of a text box to an attribute of the Model. Although it is very simple and artificial, it shows a great deal of the API, that you're most likely to use first.

<html>
  <head>
    <title>BindingJS - API Example</title>
    <!-- jQuery is the only dependency of BindingJS -->
    <script src="jQuery.js"></script>
    <!-- Include BindingJS -->
    <script src="binding.js"></script>
    <!-- Include a JSON Model Adapter -->
    <script src="binding.adapter.model.json.js"></script>
    <!-- This is the external Binding Specification -->
    <script type="text/binding">
        // Select the text box
        #username {
            // Bind the value of the text box to the
            // model attribute username. $ is the Model
            // Adapter and value is a view Adapter
            value <-> $username
        }
    </script>
    <script type="text/javascript">
        // This is the Model
        var model = {
            username: "John Doe"
        }
      
        // On Page Ready
        $(function() {
            BindingJS
              .create() // Create an instance
              .template("#template") // Set the template
              .binding($("script[type='text/binding']")) // Set the Binding
              .model(model) // Set the model
              .mount("#template") // Mount the bound template
              .activate() // Activate the binding
        })
    </script>
  </head>
  <body>
      <!-- This is the Template -->
      <div id="template">
        <input id="username" type="text" />
      </div>
  </body>
</html>

As you can see, BindingJS allows you to fluently chain calls to cut down the amount of code to a minimum. In addition, all of its methods are highly polymorphic, so that you could pass the template and the binding as a string, too. To not bloat this overview, please enquire the wiki for a full documentation of BindingJS' API.

Syntax

BindingJS differentiates between Core and Convenience Concepts as well as between Binding and Structure Concepts. All Convenience Concepts could also be expressed with Core Concepts and Structure Concepts do not deal with data binding, but the structure of applications. Surprisingly there are only three real Core Binding Concepts, which are Selection, Binding and Iteration, so we explain them first.

###Selection

BindingJS' selection syntax is inspired by Less, which among other features allows to nest CSS selectors. In contrast to CSS, however, BindingJS expects Bindings instead of Style instructions.

#wrapper {
  // <Binding-1>
  div > .input, span {
    // <Binding-2>
  }
  // <Binding-3>
  div {
    div + p {
      // <Binding-4>
      // <Binding-5>
    }
    .empty {}
  }
  // <Binding-6>
}

A Scope consists of one or more CSS selectors separated by commas and a Scope Body that is enclosed in curly braces. The Scope Body may contain Bindings or other Scopes, which can be seen as a Tree of Scopes. Each Scope slices a portion out of the template, which can be refined when nesting deeper. The idea is, that any Binding applies to all elements that are matched by its enclosing Scope. In the example the first and last Binding would apply to any elements of the template which have wrapper as their id. Assuming that there is exactly one such wrapper element, the second Binding would then apply to all of its descendants which are either a span or have the class input a div as their parent. Here is the same example without nesting. Obviously more code has to be repeated now.

#wrapper {
  // <Binding-1>
  // <Binding-3>
  // <Binding-6
}
#wrapper div > .input {
  // <Binding-2>
}
#wrapper span {
  // <Binding-2>
}
#wrapper div div + p {
  // <Binding-4>
  // <Binding-5>
}
#wrapper div .empty {}

###Binding

BindingJS synchronizes values from three data targets, namely the Model, View and the Binding Scope. The binding scope is an artificial temporary variable pool that is useful to store intermediate values and give them aliases. Also, BindingJS uses it to realize Iteration. Each of these data targets is accessed through an Adapter, that has a Prefix and a Qualifier. By default the prefix of the model adapter is $ and that of the binding scope adapter is @. There are multiple view adapter such as value, text, attr or on that are already included in BindingJS. The qualifier of an adapter is a static instruction for the Adapter and is written directly behind the prefix, if that is only one character long. Otherwise it is separated by a colon from the prefix.

$username // Prefix = $,     Qualifier = username
value     // Prefix = value, Qualifier = (none)
attr:id   // Prefix = attr,  Qualiifier = id
@temp     // Prefix = @,     Qualifier = temp

Apart from adapter there are Connectors, that may manipulate values as they are propagated through a binding. BindingJS comes with a small amount of connectors such as the debug connector, but mainly you'll need them to execute your individual business logic. BindingJS allows to register new connectors, that can be easily implemented as a function receiving and producing values. A binding consists of two adapters on its ends and any number of connectors in between. All parts are connected with arrows that indicate the direction of the binding.

// Whenever the username attribute from the presentation model changes
// uppercase it and write it into value. Value refers to the elements matched
// by the selector of the surrounding scope
value <- uppercase <- $username

// Alias an attribute with the binding scope
@nI <- $netIncome

// Whenever the value of an element changes, store it in the model attribute
// username
value -> $username

There is one specialty about the binding scope adapter. If it is used within a scope, it becomes visible to all descendants of that scope. This means, that the same qualifier for the binding scope might not necessarily refer to the same value, if its used within sibling scopes.

span {
  @notTheSame <- text
}
input {
  @notTheSame <- value
}

One use case for the binding scope adapter is to realize dependent view elements. Imagine the situation, where you want to only enable a submit button, if the value of a text box is not empty.

div {
  // Define in parent
  @isEmpty <~ false
  input {
    @isEmpty <- value === ""
  }
  button {
    attr:enabled <- !@isEmpty
  }
}

###Iteration

It is common to iterate certain parts of a user interface for instance to show a list of names or options. In BindingJS this can be done by providing additional information after the selector of a scope.

// With Element and Index
li (@element, @index: $collection) {
  // Do something with @element and @index
  text <- @index + ". " + @element.name
}

// Element only
li (@name: $names) {
  // Do something with @name
  text <- @name
}

// Conditionally hide or display elements
div (@showFooter) {
  ...
}

As you can see, conditionally hiding or displaying is a special case of iteration. It basically means to iterate something zero times or once. This means that if the last adapter or expression within the brackets after a sc

View on GitHub
GitHub Stars121
CategoryDevelopment
Updated4mo ago
Forks5

Languages

JavaScript

Security Score

77/100

Audited on Nov 6, 2025

No findings