Skip to content

Releases: canjs/canjs

preventing $.event.add and $.event.remove when bind/unbind are called on Document Fragments

Repo & website updates

03 Oct 16:42
Compare
Choose a tag to compare

This release fixed some things in the repo and on the website.

Diff: v3.10.2...v3.10.3

Fixing binding to getters that use `lastSetVal`

08 Sep 20:14
Compare
Choose a tag to compare

can-define@1.4.5 - Fixing binding to getters that use lastSetVal

This fixes an issue where if you have a getter using lastSetVal like:

  place: {
    get: function(lastSet){
      if(lastSet) {
        return lastSet;
      }
    }
  }

and were binding to it in a template like:

    {{#if place}}
      THERE IS A PLACE
    {{/if}}

The template would not be updated when setting place.

can-reflect-promise@1.1.1 - moved docs to can-infrastructure

Helpful Warnings and Fix for `parent.replacements` Issue

07 Sep 00:45
Compare
Choose a tag to compare

Notable Bug Fixes / Docs

can-define@1.4.4 - Helpful warnings

Warn when setting a property that has only a zero-arg getter

var VM = DefineMap.extend({
    derivedProp: {
        get: function() {
            return "Hello World";
        }
    }
});

var vm = new VM();
vm.derivedProp = 'prop is set';

can-define: Set value for property derivedProp ignored, as its definition has a zero-argument getter and no setter

Warn when value property is assigned an object

DefineMap.extend({
    options: {
        value: {
            foo: 'bar',
            abc: 'xyz'
        }
    }
});

can-define: The value for options is set to an object. This will be shared by all instances of the DefineMap. Use a function that returns the object instead.

Warn when value property is assigned a constructor

DefineMap.extend({
    options: {
        value: DefineMap
    }
});

can-define: The "value" for options is set to a constructor. Did you mean "Value" instead?

Warn when a constructor is supplied as a type definition

var VM = DefineMap.extend({
    currency: {
        type: Currency
    }
});

can-define: the definition for currency uses a constructor for "type". Did you mean "Type"?

can-component@3.3.4 - warns if viewModel is assigned a DefineMap

A warning will be shown if a constuctor is passed as the viewModel property (with a lower-case v) of a can-component since ViewModel should be used:

var VM = DefineMap.extend({});
Component.extend({
    tag: 'can-vm1-test-component',
    viewModel: VM
});

can-component: Assigning a DefineMap or constructor type to the viewModel property may not be what you intended. Did you mean ViewModel instead? More info: https://canjs.com/doc/can-component.prototype.ViewModel.html

can-route@3.2.3 - Remove extra warnings

This removes warnings when two routes match, but one has a trailing /:

WARN: two routes were registered with matching keys:
	(1) route("internet", {"page":"internet"})
	(2) route("internet/", {"page":"internet"})
(1) will always be chosen since it was registered first

can-view-live@3.2.3 - running add,set,remove,move in the Observation update queue

This fixes an issue where parent.replacements was null at times in the register function in cases where an {{#if ...}} surrounded an {{#each ...}} and the list was modified in the same batch as the if was toggled to remove the each:

{{#if show}}
  {{#each items as item}}
    {{item}}
  {{/each}}
{{/if}}
show = false;
list.replace([ 'two', 'three' ]);

Other Bug Fixes

v3.10.0

29 Aug 23:28
Compare
Choose a tag to compare

New Features

New Bindings Syntax

can-stache-bindings has intuitive new syntaxes for event, one-way bindings, and two-way bindings:

  • on:event="key()" for event binding.
  • prop:from="key" for one-way parent-to-child binding.
  • prop:to="key" for one-way child-to-parent binding.
  • prop:bind="key" for two-way binding.

To upgrade to the new binding syntaxes, try out the codemod in can-migrate.

Named inline partials

You can now define reusable partials inside your templates!

In the example below, addressTemplate is defined as a partial and then used later in the same template:

{{<addressTemplate}}
  <div>{{street}}, {{city}}</div>
{{/addressTemplate}}

<div>
  {{#with business.address}}
    {{>addressTemplate}}
  {{/with}}
</div>
<ul>
  {{#each business.people}}
    <li>
      {{fullName}}, {{birthday}}
      {{>addressTemplate address}}
    </li>
  {{/each}}
</ul>

Learn more in the {{<partialName}} docs.

{{debugger}

In development, the new {{debugger}} stache helper will break at the given point in the template so you can inspect the current scope in the browser’s console.

Learn more in the {{debugger}} docs.

Control whitespace in stache templates

Sometimes it’s useful to prevent stache from rendering whitespace, such as when you want to target an element with the :empty CSS selector.

If you add - to your magic tags, you can have this:

<div>
	{{-#if user.isMarried-}}
		Mrs
	{{-else-}}
		Miss
	{{-/if-}}
</div>

…rendered as this:

<div>{{#if user.isMarried}}Mrs{{else}}Miss{{/if}}</div>

Learn more in the Whitespace Control docs.

Complete list of minor updates

can-define@1.4.0 - Observable indexed value changes
can-event@3.7.0 - RemoveEventListener can now remove all events and IE9 bug fixes
can-stache@3.3.0 - Whitespace Control
can-stache@3.4.0 - Updating can-view-parser to support new binding syntaxes
can-stache@3.5.0 - Added debugger helper
can-stache@3.6.0 - Adding inline Named Partials functionality
can-stache-bindings@3.5.0 - New colon binding syntaxes
can-stache-bindings@3.6.0 - on:vm:event and on:el:event
can-stache-bindings@3.7.0 - Specify events for data bindings, other fixes
can-vdom@3.2.0 - Adds the Node type to the exported globals in make-window
can-view-parser@3.5.0 - Using can-attribute-encoder for encoding attributes

New Packages

can-attribute-encoder

Encode and decode strings to be used as attribute names in the DOM:

var encodedAttributeName = encoder.encode("{(^$foo/bar baz)}");

encoder.decode(attributeName); // -> "{(^$foo/bar baz)}"

can-element

Create customelement classes with CanJS.

var Element = require("can-element").Element;
var stache = require("can-stache");
var define = require("can-define");

var view = stache("Hello {{name}}");

var MyApp = class extends Element {
    static get view() {
        return view;
    }
};

define(MyApp.prototype, {
    name: {
        value: "world"
    }
});

customElements.define("my-app", MyApp);

var el = document.createElement("my-app");

el.name; // -> "world"

can-kefir

Integrate KefirJS streams directly within can-stache and other parts of CanJS.

var Kefir = require("can-kefir");

var countTo3Stream = Kefir.sequentially(1000,[1,2,3]);

var view = stache("<p>Number: {{countTo3Stream.value}}</p>");

var frag = view({
    countTo3Stream: countTo3Stream
});

document.body.appendChild(frag);

can-observe

Create observable objects that acts as a proxy for target objects.

var dog = observe({});

dog.addEventListener('name', function(){
	// Name changed!
});

dog.name = 'Wilbur';

Bug Fixes, Documentation Improvements

can-component@3.3.1 - https://github.com/canjs/can-component/releases/tag/v3.3.1
can-component@3.3.2 - Updating can-stache-key to receive bug fixes
can-component@3.3.3 - removed can-* pre-releases3
can-compute@3.3.2 - Updating can-stache-key
can-compute@3.3.3 - Use typeof to check for console & Update can-stache-key
can-connect@1.5.7 - Replaced console with canLog
can-connect@1.5.8 - Removing deprecated can-types method
can-connect-feathers@3.6.1
can-connect-feathers@3.6.2
can-control@3.2.1 - Updating can-stache-key
can-control@3.2.2 - Updating can-stache-key to receive bug fixes
can-define@1.4.1
can-define@1.4.2 - Calling define adds a CID
can-define@1.4.3
can-ejs@3.1.3 - Updating can-stache-key
can-ejs@3.1.4 - Updating can-stache-key to receive bug fixes
can-event@3.6.2 - Handle Console Not Being Present
can-event@3.7.1 - can-event/batch/batch logs a warning on missing stop
can-map@3.3.2 - Updating can-stache-key
can-map@3.3.3 - Updating can-stache-key to receive bug fixes
can-observation@3.3.3 - Use canLog Instead of console
can-observation@3.3.4 - deprecated
can-observation@3.3.5
can-stache@3.3.1 - Warn when can-stache-bindings is not imported
can-stache@3.3.2 - Plain js objects now work with subtemplate
can-stache@3.3.3 - Fixed Test for can-jquery
can-stache@3.3.4 - Updating can-stache-key
can-stache@3.5.1 - Fixing issue with debugger helper in production
can-stache@3.5.2 - Updating can-stache-key to receive bug fixes
can-stache@3.6.1 - Warning when using on:, :to, :from, :bind and not importing can-stache-bindings
can-stache@3.6.2 - Doc update: warnings on recursive named partials
can-stache-bindings@3.4.5 - Docs and Deps
can-stache-bindings@3.4.6 - Improved warnings
can-stache-bindings@3.4.7 - Updating can-stache-key
can-stache-bindings@3.6.1 - Updating can-stache-key to receive bug fixes
can-stache-bindings@3.6.2 - encoding attribute before looking for callback
can-stache-bindings@3.6.3 - Fixed endsWith in IE
can-stache-key@0.1.0 - minor version bump to allow dependent packages to receive bug fixes
can-util@3.9.9 - Change async tests to polling
can-view-autorender@3.1.1 - Updated dependencies
[can-view-scope@3.3.3 - Updating can-stache-ke...

Read more

v3.9.1

09 Aug 16:27
Compare
Choose a tag to compare

v2.3.32

19 Jul 19:04
Compare
Choose a tag to compare

Fix exposing module in CommonJS format: #3294

can-reflect, react-view-model, ndjson streams, slots

07 Jul 22:55
Compare
Choose a tag to compare

Big Changes

can-reflect and can-symbol

can-reflect and can-symbol - Created a unified interface for all observable CanJS types. For example, to set a name property on a can.Map, DefineMap, or SimpleMap, you can now use:

canReflect.setKeyValue(map,"name", "my map");

This let us use the much faster can-observation throughout CanJS's codebase, resulting in improved application initialization performance times, especially if you are using Call Expressions which can keep everything as an Observation.

React View Model

If you are using React, but like the clarity and ease of CanJS's DefineMap ViewModels, you are in luck. react-view-model lets you create react components that use DefineMap as a nicely unit-testable ViewModel. No more calling setState. Instead just change a property on your ViewModel.

The following creates a React CounterComponent with a CounterViewModel:

var CounterViewModel = DefineMap.extend({
  count: 'number',
  increment: function() {
    return this.count++;
  },
});

var CounterComponent = reactViewModel("CounterComponent", CounterViewModel, (counterVM) => {
  return (
    <div onClick={ counterVM.increment.bind(counterVM) }>
      Count: {counterVM.count} (Click Me)
    </div>
  );
});

NDJSON streams

Apparently 2016 was the year of streams. I disagree, it's going to be 2018 as only Google Chrome and Safari support fetch and ReadableStream. However, what a year 2018 will be! I'll try to explain:

  • fetch is the new, much more powerful, XMLHTTPRequest object. It lets you do "AJAX".
  • It's also going to let you access a streaming response body through ReadableStream interface.
  • NDJSON is a format that streams JSON.

Combining these ideas, it's possible to stream out a database response (or even cached data) in NDJSON and have the page display information as soon as it gets it:

ndjson-stream-json

EPIC PERFORMANCE WIN!

We created two modules to help use streams:

  • can-ndjson-stream - Use to access the raw response stream of fetch and convert it to a stream of JavaScript objects.
  • can-connect-ndjson - Stream an NDJSON response into a DefineList.

Component slots

The Web Components <slot> and <template> specifications promise to make customizing native custom elements easy. Until that glorious day happens, we've added our own <can-slot> and <can-template>.

Let’s say we’re creating a modal component that we want to make customizable by passing in templates for its header, body, and footer:

Component.extend({
  tag: 'ui-modal',
  view: stache(`
    <div class="modal">
      <div class="modal-content">
        <div class="modal-header">
          <can-slot name="header" />
        </div>
        <div class="modal-body">
          <can-slot name="body" />
        </div>
        <div class="modal-footer">
          <can-slot name="footer" />
        </div>
      </div>
    </div>
  `)
});

In the component’s template, we’re providing the structure around the header, body, and footer. Then, we use can-slot to allow other components to specify what should be inserted into those sections.

Now let’s use our ui-modal component:

const renderer = stache(`
  <ui-modal>
    <can-template name="header">
      <h5 class="modal-title">{{titleText}}</h5>
    </can-template>
    <can-template name="body">
      <p>{{bodyText}}</p>
    </can-template>
    <can-template name="footer">
      <button type="button" class="btn btn-primary">{{primaryButtonText}}</button>
      <button type="button" class="btn btn-secondary">{{secondaryButtonText}}</button>
    </can-template>
  </ui-modal>
`);

renderer({
  titleText: 'Discard your changes?',
  bodyText: 'Your data will not be saved.',
  primaryButtonText: 'Discard',
  secondaryButtonText: 'Cancel'
});

In the template, we’re using can-template to specify what should be inserted into the can-slot sections in our ui-modal component. Then, we’re rendering that template with the object provided to renderer.

The final HTML structure will look like this:

<ui-modal>
  <div class="modal">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Discard your changes?</h5>
      </div>
      <div class="modal-body">
        <p>Your data will not be saved.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-primary">Discard</button>
        <button type="button" class="btn btn-secondary">Cancel</button>
      </div>
    </div>
  </div>
</ui-modal>

Learn more in the <can-slot> and <can-template> documentation.

v3.8.2

v3.8.1