---
title: CanJS 2.3 Release
description: CanJS 2.3 release notes and examples.
image: https://www.bitovi.com/hubfs/canjs-background-blue-1.gif
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting)
- ![Project Management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project Management](https://www.bitovi.com/services/agile-project-management-consulting)
- ![Product Design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product Design](https://www.bitovi.com/services/product-design-consulting)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting)
- [Design systems](https://www.bitovi.com/services/axure-figma-migration)
- [React](https://www.bitovi.com/services/frontend/react-consulting)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about delivering products and solving problems.
  
  ](https://www.bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships)
- [![Academy](https://www.bitovi.com/hubfs/icon%20-%20academy%20(4).svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse or contribute to our community
  
  ](https://www.bitovi.com/open-source)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

 January 22, 2016

# CanJS 2.3 Release

 CanJS 2.3 release notes and examples.

![Justin Meyer](https://www.bitovi.com/hubfs/justin.jpeg)

 Justin Meyer

Share:

[![Twitter](https://www.bitovi.com/hubfs/limbo-generated/_astro/twitter-white.os3xLc3C_Z2nW4or.svg) ](https://twitter.com/intent/tweet?text=) [![Reddit](https://www.bitovi.com/hubfs/limbo-generated/imgs/icons/reddit.png) ](http://reddit.com/submit?url=)

 

Today, we're announcing the release of CanJS 2.3. Here's the [2.3.11 download](https://github.com/bitovi/canjs.com/archive/v2.3.11.zip), its [npm page](https://www.npmjs.com/package/can), and its [changelog](http://canjs.com/guides/changelog.html). This release includes over 800 commits, a bunch of bug fixes, performance improvements, and new features that improve the expressive power of the framework.

This article highlights 2.3's biggest new features:

- [{{#each}} diffing](https://www.bitovi.com/blog/canjs-2-3-release#diffing) - Perform minimal DOM modifications if `#each` is passed different list instances.
- [Call Expressions](https://www.bitovi.com/blog/canjs-2-3-release#callexpressions) - Call methods in stache templates like: `{{ capitalize( pluralize('person',2) ) }}`.
- [Binding Syntaxes](https://www.bitovi.com/blog/canjs-2-3-release#bindingsyntaxes) - Control the direction of data bindings and listen to `viewModel` events in stache.
- [Key Operators](https://www.bitovi.com/blog/canjs-2-3-release#keyoperators) - Pass functions in stache or use template variables.
- [Performance Improvements](https://www.bitovi.com/blog/canjs-2-3-release#performance) - Faster computes and live binding.

For information on 3.0 and beyond, checkout [3.0's Roadmap Discussion](http://forums.donejs.com/t/canjs-roadmap-discussion/75).

## {{#each}} diffing

With the introduction of [can.compute](http://canjs.com/docs/can.compute.html) in CanJS 1.1 and the [define](http://canjs.com/docs/can.Map.prototype.define.html) plugin in CanJS 2.1, one of CanJS's best features has been its ability to derive new values from other values. This pattern has taken hold in the React community and for good reason - these types of apps feel like mathematical equations.

For example, in TodoMVC, the displayed todos are derived from the `todos` loaded from the server and the route's `filter` value:

```
displayList: function () {
    var filter = route.attr('filter');
    return this.attr('todos').filter(function (todo) {
        if (filter === 'completed') {
            return todo.attr('complete');
        }
        else if (filter === 'active') {
            return !todo.attr('complete');
        }
        else {
            return true;
        }
    });
}
```

The todos returned by `displayList` are converted into a list of `<li>` elements with `{{#each}}`:

```
{{#each displayList}}
   <li> .... </li>
{{/each}}
```

Prior to 2.3, when a new todo is created, `displayList` would be re-calculated and every `<li>` would be removed and re-created. With 2.3, `{{#each}}` performs a diff of the new list and old list, and adds only a single `<li>` for the new todo.

Checkout the difference in performance between 2.2 without the diff and 2.3 with the diff by adding a new todo to a list of 1000 todos:

**2.2 Demo**

[JS Bin on jsbin.com](http://jsbin.com/bakinu/2/embed?output)

**2.3 Demo**

[JS Bin on jsbin.com](http://jsbin.com/xamegi/7/embed?output)

With 2.3, you can now take full advantage of CanJS's ability to derive values from other values without worrying about performance. In future releases, with the aid of [can-derive](https://github.com/canjs/can-derive), we should be able to speed this up even more (*from a linear diff to a logarithmic binary tree insert*).

## Call Expressions

2.3 adds [call expressions](http://canjs.com/docs/can.stache.expressions.html#section_Callexpression). These look similar to normal JavaScript function calls. For example:

```
{{ pluralize(type, ages.length) }}
```

Call expressions have three advantageous over normal helper functions:

- They are passed values instead of computes
- They can be nested
- They have more easily understood scope lookup rules

### Call expressions pass values instead of computes

By default, stache and mustache helpers are passed computes that represent an observable argument. For example, the pluralize helper in the following fiddle needs to get the value from the `type()` and `count()` compute arguments:

[JS Bin on jsbin.com](http://jsbin.com/visage/embed?js,output)

Passing computes was a legacy decision that has been confusing with hindsight. Fortunately, call expressions are here to simplify things. They pass the value of the observable argument. In the following example, notice how pluralize simply uses the `type` and `count` values:

[JS Bin on jsbin.com](http://jsbin.com/wifemu/embed?js,output)

### Nested call expressions

Call expressions can be nested as part of other call expressions or other helper expressions like:

```
{{ capitalize( pluralize(type, args.length) ) }}
{{#each statsForTeam( teamId.id ) }}
```

This makes it easier to compose behaviors. In the following example, `statsForTeam` is able to get a list of scores for a team. Using `#each`'s diffing, the list of scores updates with minimal DOM changes if the source list of scores changes. Notice that the *yellow* elements stay in place as stats are added:

[JS Bin on jsbin.com](http://jsbin.com/nalowa/embed?html,js,output)

### Scope lookup rules

Call expression methods are found in in the [Scope](http://canjs.com/docs/can.view.Scope.html) first and only if nothing is found, the [HelperOptions](http://canjs.com/docs/can.stache.helperOptions.html) scope is searched. This is in contrast to helper expression methods that find methods in the following order:

1. search the current context
2. search the helper scope
3. search the scope

Notice how the `pluralize` *helper expression* calls the `pluralize` helper despite there being a `pluralize` method in the scope:

[JS Bin on jsbin.com](http://jsbin.com/buwana/embed?js,output)

Notice how the `pluralize` *call expression* calls the `pluralize` method in the scope.

[JS Bin on jsbin.com](http://jsbin.com/fasifu/embed?js,output)

Call expressions make calling functions from stache more simple and straightforward.

## Binding Syntaxes

CanJS 2.3 supports new binding syntaxes that:

- enable **fine grained** binding behavior,
- support **dynamic bindings**.

This section will go through the new binding syntaxes and how they accomplish these goals. But first, lets take a refresher on "bindings" and CanJS's older binding syntaxes.

### 2.2 Binding Syntaxes

CanJS 2.2 supports two main types of binding syntaxes:

- Event bindings - used to listen to an event and call a method in the scope.
- Data bindings - used to tie a scope value to a value on either the `viewModel` of a component or a `property` or `attribute` of a DOM element.

These bindings expressed themselves in three different syntaxes:

| Type | Example |
| --- | --- |
| **Event** DOM | `<my-comp can-click="scopeMethod"/>` |
| **Data - 2 way** scope to viewModel | `<my-comp vm-prop="{scopeProp}"/>` |
| **Data - 2 way** scope to DOM | `<input can-value="{scopeProp}"/>` |

 

The 2.2 syntaxes have multiple issues.

First, they are incompatible with **dynamic bindings**. Dynamic bindings are binding behaviors that change as attributes are added and removed to a component. For example:

```
<my-component vm-prop="{ {{keyName}} }"{{/value}}/>
<my-component {{#if value}}vm-prop="{key}"{{/value}}/>
```

It's possible that someone wants to use magic tags to dynamically control the bindings applied to a component. The 2.2 syntaxes made this difficult or outright impossible.

Second, while two-way bindings are useful for establishing cross communication between components, they can sometimes make debugging more difficult. For example, a parent component might want to pass a value to a child component, but not immediately get updates as the child changes its value. A common scenario might be an autocomplete that should only retrieve suggestions after a user has entered more than two characters. To make situations like these easier to code and reason about, our new syntaxes enable more **fine-grained control** of binding behavior.

### New Syntaxes

In 2.3, bindings use the following syntax rules:

- `{left}="right"` - update `left` with the value of `right`.
- `(left)="right"` - listen to the `left` event and do `right` when it happens.
- `{(left)}="right"` - two way bind `left` and `right`.
- `$` - act upon the *element's* events, attributes, or properties instead of the *viewModel's*.
- `^` - reverse the direction of the binding.

The following lists all the combinations of those syntax rules:

| Type | Example |
| --- | --- |
| **event** viewModel | `<my-comp (vm-event)="scopeMethod()"/>` Listens to *vmEvent* on the component's viewModel. |
| **event** DOM | `<element ($click)="scopeMethod()"/>` Listens to *click* on the element. |
| **1 way** scope to viewModel | `<my-comp {vm-prop}="scopeProp"/>` Updates the viewModel's *vmProp* property with the value of *scopeProp*. `<my-comp {vm-prop}="callExpression()"/>` Updates the viewModel's *vmProp* property with the value of a *callExpression*. |
| **1 way** viewModel to scope | `<my-comp {^vm-prop}="scopeProp"/>` Updates *scopeProp* with the viewModel's *vmProp* property. |
| **1 way** scope to attribute | `<element {$el-prop}="scopeProp"/>` Updates the element's *el-prop* attribute or property with the value of *scopeProp*. This is equivalent to `el-prop="{{scopeProp}}"`. |
| **1 way** attribute to scope | `<input {^$value}="name"/>` Updates *name* in the scope with the the element's *value* property. |
| **2 way** scope to viewModel | `<my-comp {(vm-prop)}="scopeProp"/>` Two way binds the viewModel’s *vmProp* with the value of *scopeProp*. |
| **2 way** scope to attribute | `<element {($el-prop)}="scopeProp"/>` Two way binds the element’s *el-prop* attribute or property with the value of *scopeProp*. |
| **2 way** attribute to viewModel | `<my-comp vm-prop="value"/>` Sets the viewModel's *vmProp* to the value of the attribute. |

### Fine Grained Control

Lets take a look at what these new bindings can do!

#### Example 1: DOM event bindings and two way bindings

The following example creates a `<my-input>` element that behaves similar to a native input element. It uses a DOM event binding to update its `value` property as the user types.

```
($keydown)='updateValue(%event)'
```

The example cross binds the `<my-input>`'s value and a native input element's value to a *person's* `name` property.

```
<my-input {(value)}="name"/>
<input {($value)}="name"/>
```

Notice how when one element's value changes, the other element's value will change.

[JS Bin on jsbin.com](http://jsbin.com/fisedi/4/embed?html,output)

#### Example 2: ViewModel event bindings

One way bindings and *viewModel* event handlers can be used to setup one way data flows between components.

The following example only updates `name` when there is an even number of characters. It does this by first defining an `updateNameOnEven` method that takes a new name and only updates `<person-edit>`'s *viewModel* when name has an even number of characters:

```
updateNameOnEven: function(newName){
  if(newName.length % 2 === 0) {
    this.attr("name", newName);
  }
}
```

Next, it listens to when `<my-input>`'s `value` changes and calls `updateNameOnEven`, passing it the `value` of `<my-input>`:

```
 (value)="updateNameOnEven( %viewModel.value )"
```

Finally, it listens to the `<input>`'s *oninput* event and calls `updateNameOnEven`, passing it the `value` of the `<input>`:

```
 ($input)="updateNameOnEven( %element.value )"
```

Notice how the name only changes on every other character:

[JS Bin on jsbin.com](http://jsbin.com/yokiqo/3/embed?html,js,output)

#### Example 3: Custom ViewModel event bindings

The viewModel events you can listen to are not limited to the *named* events produced whenever a property changes. In the following example, the `<person-edit>` module produces `"saved"` events when the *save* button is clicked using `can.trigger`:

```
can.trigger(self,"saved");
```

`<person-page>` listens to these events and calls its `addMessage` method with:

```
(saved)="addMessage('Saved')"
```

Notice that when *save* is clicked, "Saved" messages will temporarily appear:

[JS Bin on jsbin.com](http://jsbin.com/najumeg/3/embed?html,js,output)

## Key Operators

Stache adds the following three new key operators:

- `@key` - at operator - Return whatever value is **at** `key`. Pass the function or compute at *key* instead of its return value.
- `~key` - compute operator - Pass a compute instead of the value at `key`.
- `*key` - template variable operator - Reference a local template variable.

These `key` operators can be used everywhere [keys](http://canjs.com/docs/can.stache.key.html) are used:

- **helper expressions** - The arguments passed to stache helpers like `{{myHelper key1 key2}}`.
- **call expressions** - The arguments passed to call expressions like `{{myHelper( key1, key2 )}}`.
- **data bindings** - The new binding syntaxes like `{vm-prop}="key"`.
- **event bindings** - The arguments passed to an `(event)` binding like `($click)="method( key )"`.

### At operator (`@key`)

The *At operator* is used to pass a function or compute as an argument instead of the function or compute's return value. This can be a great way of isolating concerns between components.

For example, the following passes `<person-page>`'s `save` method to `<person-edit>` with:

```
{onsave}="@save"
```

This allows `<person-edit>` to be able to call `onsave` without having to define the *save* behavior itself. Notice how the `<person-edit>` disables the form elements when *save* is clicked.

[JS Bin on jsbin.com](http://jsbin.com/sivitiw/embed?html,js,output)

When the *At operator* is used in **helper expressions**, a compute can still be passed. Notice how `method` is a compute that returns the `func` function:

[JS Bin on jsbin.com](http://jsbin.com/binupa/4/embed?js,output)

The `@` symbol can be used multiple times within a key reference. For example, if `models` was a collection of `can.Model`s like:

```
var models = {
  Task: can.Model.extend({resource: "/tasks"},{}),
  ...
}
```

To pass the `Task.findAll` method, you might do:

```
<my-grid {get-list}="models@Task@findAll"/>
```

The first `@` symbol makes sure that the `Task` function is not called and the second `@` makes sure that `findAll` is not called.

## Compute operator (`~key`)

In all key uses other than **helper expressions** (call expressions, data and event bindings), values are passed instead of computes. Generally speaking, values are what you want. However, sometimes it's nice to get a compute that lets you read, update, and listen to changes in that value. The *Compute operator* lets you pass a compute for that value instead of the value itself.

The most important place to be aware of this functionality is calling `{{#each}}` helper with a **call expression**. The `{{#each}}` helper needs a compute to perform diffing. If you call `{{#each}}` as helper expression like:

```
{{# each statsForTeam( teamId.id ) }}
```

... the results of `statsForTeam` will be passed as a compute. However, if you call `{{#each}}` as a call expression like:

```
{{# each( statsForTeam( teamId.id ) ) }}
```

... the results of `statsForTeam` will be passed as list. The solution for this is to use the compute operator as follows:

```
{{# each( ~statsForTeam( teamId.id ) ) }}
```

In the following example `each` is in the scope, so the alias `eachOf` is used instead:

[JS Bin on jsbin.com](http://jsbin.com/lohiyi/2/embed?html,js,output)

### Template variable operator

In 2.3, you can create variables local to a template. Templates have a special context that can be used to store observable values. These observable values are useful for connecting values across components without the need to create a value in the parent component.

Template variables are indicated with `*`. The following example uses an `*editing` variable to connect the `<driver-select>` and `<edit-plate>` components. `<driver-select>` exports the selected driver to `*editing` with:

```
<driver-select {^selected}="*editing"/>
```

`<edit-plate>` two way binds to the `*editing.licensePlate` with:

```
<edit-plate {(plate-name)}="*editing.licensePlate"/>
```

Click a driver and edit their plate number:

[JS Bin on jsbin.com](http://jsbin.com/xanopi/2/embed?html,js,output)

## Performance Improvements

Finally, the last improvement we made is improving the performance of computes. As of 2.3.10, the spinning circle demo is about 20% faster than 2.2.9:

### 2.3

[JS Bin on jsbin.com](http://jsbin.com/repita/1/embed?output)

### 2.2

[JS Bin on jsbin.com](http://jsbin.com/qudegu/4/embed?output)

[![Tag for open source](https://www.bitovi.com/hubfs/limbo/icons/tag.svg) open source ](https://www.bitovi.com/blog/topic/open-source)

 Previous Post

![canjs-background-blue.gif](https://www.bitovi.com/hs-fs/hubfs/Bitovi_July_2016_Theme/Images/canjs-background-blue.gif?height=117&name=canjs-background-blue.gif) [ Routing in CanJS ](https://www.bitovi.com/blog/routing-in-canjs)

  

 Next Post

![donjs-banner.jpg](https://www.bitovi.com/hs-fs/hubfs/donjs-banner.jpg?height=117&name=donjs-banner.jpg) [ Object.observe is dead, long live ES6 Proxies ](https://www.bitovi.com/blog/long-live-es6-proxies)

```json
{
  "@context" : "http://schema.org",
  "@type" : "Organization",
  "address" : {
    "@type" : "PostalAddress",
    "addressCountry" : "United States",
    "addressLocality" : "Libertyville",
    "addressRegion" : "IL",
    "postalCode" : "60048",
    "streetAddress" : "1134 Pine Tree Lane "
  },
  "alternateName" : "Bitovi",
  "areaServed" : {
    "@type" : "GeoCircle",
    "geoMidpoint" : {
      "@type" : "GeoCoordinates",
      "latitude" : "41.8781",
      "longitude" : "87.6298"
    },
    "geoRadius" : "5000 km"
  },
  "description" : "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
  "email" : "contact@bitovi.com",
  "image" : "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
  "logo" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
  "mainEntityOfPage" : {
    "@id" : "https://www.bitovi.com/blog/canjs-2-3-release",
    "@type" : "WebPage",
    "description" : "CanJS 2.3 release notes and examples."
  },
  "naics" : "541511",
  "name" : "Bitovi Web App Consulting",
  "sameAs" : [ "https://www.facebook.com/BitoviLLC/", "https://twitter.com/bitovi", "https://www.linkedin.com/company/bitovi" ],
  "telephone" : "312-620-0386",
  "url" : "http://bitovi.com"
}
```

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Justin Meyer"
  },
  "dateModified" : "September 30, 2016, 5:11:02 AM",
  "datePublished" : "2016-01-22 19:16:36",
  "description" : "CanJS 2.3 release notes and examples.",
  "headline" : "CanJS 2.3 Release",
  "image" : {
    "@type" : "ImageObject",
    "url" : "http://cdn2.hubspot.net/hubfs/2171535/canjs-background-blue-1.gif"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg"
    },
    "name" : "Bitovi"
  }
}
```