can
Version:
MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.
926 lines (650 loc) • 34.4 kB
HTML
<!--####################################################################
THIS IS A GENERATED FILE -- ANY CHANGES MADE WILL BE OVERWRITTEN
INSTEAD CHANGE:
source: [object Object]
@page migrate-3
######################################################################## -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>CanJS - Migrating to 3.0</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="stylesheet" type="text/css" href="./static/bundles/bit-docs-site/static.css">
<link rel="shortcut icon" sizes="16x16 24x24 32x32 48x48 64x64" href="/docs/images/canjs_favicon.ico">
<link rel="apple-touch-icon" sizes="57x57" href="../docs/images/canjs_favicon_57x57.png">
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="../docs/images/canjs_favicon_57x57.png">
<link rel="apple-touch-icon" sizes="72x72" href="../docs/images/canjs_favicon_72x72.png">
<link rel="apple-touch-icon" sizes="114x114" href="../docs/images/canjs_favicon_114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="../docs/images/canjs_favicon_128x128.png">
<link rel="apple-touch-icon" sizes="144x144" href="../docs/images/canjs_favicon_144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="../docs/images/canjs_favicon_152x152.png">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta name="apple-mobile-web-app-status-bar-style" content="white-translucent">
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-2302003-11', 'auto');
ga('send', 'pageview');
</script>
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger"/>
<label for="nav-trigger">Menu</label>
<div id="everything">
<div id="left" class="column">
<div class="top-left">
<div class="brand">
<div class="logo">
<a href="../index.html" alt="CanJS"></a>
<div class="dropdown project-dropdown">
<a href="https://donejs.com/">DoneJS</a>
<a href="http://stealjs.com/">StealJS</a>
<a href="http://jquerypp.com/">jQuery ++</a>
<a href="https://funcunit.com/">FuncUnit</a>
<a href="http://documentjs.com/">DocumentJS</a>
</div>
</div>
<div class="version">
<div class="version-number">
3.0.0
</div>
<div class="dropdown version-dropdown">
<a href="https://v2.canjs.com">2.3.27</a>
</div>
</div>
</div>
<div class="search-bar">
<p>
</p>
</div>
</div>
<div class="bottom-left">
<div class="social-side-container">
<ul class="social-side">
<li>
<a class="header-mobile github" href="https://github.com/canjs/canjs" target="_blank"><img class="social-icon-small" src="../docs/images/github.png">Github</a>
</li>
<li>
<a class="header-mobile twitter" href="https://twitter.com/canjs" target="_blank"><img class="social-icon-small" src="../docs/images/twitter.png">Twitter</a>
</li>
</ul>
<ul class="social-side">
<li>
<a class="header-mobile" href="https://gitter.im/canjs/canjs" target="_blank">Chat</a>
</li>
<li>
<a class="header-mobile" href="http://forums.donejs.com/c/canjs" target="_blank">Forum</a>
</li>
</ul>
</div>
<ul>
<li class="
parent
expanded">
<a class="page"
href="guides.html"
title="Welcome to CanJS! These guides are here to help you develop and improve your relationship with CanJS. After all, picking a JavaScript framework is a commitment. We want CanJS to be the
framework you marry. This page helps you know how advance through the different stages of this
relationship:">
Guides
</a>
<ul>
<li>
<span>introduction</span>
<ul>
<li class="
">
<a class="page"
href="guides/mission.html"
title="Learn about CanJS's mission, why it matters, and how we've worked (and will keep working) to accomplish it.">
Mission
</a>
</li>
<li class="
">
<a class="page"
href="guides/technical.html"
title="">
Technical Highlights
</a>
</li>
<li class="
">
<a class="page"
href="guides/who-uses-canjs.html"
title="">
Who uses CanJS?
</a>
</li>
</ul>
</li>
<li>
<span>experiment</span>
<ul>
<li class="
">
<a class="page"
href="guides/chat.html"
title="This guide walks through building real time chat application with CanJS's Core libraries. It takes about 30 minutes to complete.">
Chat Guide
</a>
</li>
<li class="
">
<a class="page"
href="guides/todomvc.html"
title="This guide walks through building a slightly modified version of TodoMVC with CanJS's Core libraries and can-fixture. It takes about 1 hour to complete.">
TodoMVC Guide
</a>
</li>
<li class="
">
<a class="page"
href="guides/atm.html"
title="This guide walks through building and testing an ATM application with CanJS's
Core libraries. It teaches how to do test driven development (TDD)
and manage complex state. It takes about 2 hours to complete.">
ATM Guide
</a>
</li>
<li class="
">
<a class="page"
href="guides/setup.html"
title="CanJS is packaged in multiple ways so that it can fit into any development workflow. Learn how to setup CanJS in different environments.">
Setting up CanJS
</a>
</li>
</ul>
</li>
<li>
<span>commitment</span>
<ul>
<li class="
">
<a class="page"
href="guides/api.html"
title="This page walks through how to use and understand CanJS's API documentation.">
API Guide
</a>
</li>
<li class="
">
<a class="page"
href="guides/examples.html"
title="">
Examples
</a>
</li>
<li class="
">
<a class="page"
href="roadmap.html"
title="Learn about CanJS's future plans and how we make them, and how you can influence them.">
Roadmap
</a>
</li>
<li class="current
parent
expanded">
<a class="page"
href="migrate-3.html"
title="">
Migrating to 3.0
</a>
</li>
</ul>
</li>
<li>
<span>contribute</span>
<ul>
<li class="
">
<a class="page"
href="guides/contributing/bug-report.html"
title="Learn how to submit a bug report.">
Bug Report
</a>
</li>
<li class="
">
<a class="page"
href="guides/contributing/code.html"
title="Learn how contribute a code change to CanJS.">
Code
</a>
</li>
<li class="
">
<a class="page"
href="guides/contributing/documentation.html"
title="Learn how to improve CanJS's site and documentation.">
Documentation
</a>
</li>
<li class="
">
<a class="page"
href="guides/contributing/evangelism.html"
title="Learn about resources that can help you spread the word about CanJS.">
Evangelism
</a>
</li>
<li class="
">
<a class="page"
href="guides/contributing/feature-suggestion.html"
title="Learn how to suggest a feature.">
Feature Suggestion
</a>
</li>
<li class="
">
<a class="page"
href="guides/contributing/releases.html"
title="Release and hosting information for CanJS maintainers.">
Releases
</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="
">
<a class="page"
href="can-core.html"
title="The best, most hardened and generally useful libraries in CanJS.">
Core
</a>
</li>
<li class="
">
<a class="page"
href="can-ecosystem.html"
title="Useful libraries that extend or add important features to the core collection.">
Ecosystem
</a>
</li>
<li class="
">
<a class="page"
href="can-infrastructure.html"
title="Utility libraries that power the core and ecosystem collection.">
Infrastructure
</a>
</li>
<li class="
">
<a class="page"
href="can-legacy.html"
title="Former libraries that we still accept patches for, but are not under active development.">
Legacy
</a>
</li>
</ul>
</div>
</div>
<div id="right" class="column">
<div class="top-right">
<div class="top-right-top">
<ul class="top-right-bitovi">
<li class="dropdown">
<a href="http://bitovi.com" class="bitovi icon-bits">Bitovi</a>
<ul class="dropdown-menu">
<li><a href="http://bitovi.com">Bitovi.com</a></li>
<li><a href="http://bitovi.com/blog/">Blog</a></li>
<li><a href="http://bitovi.com/consulting/">Consulting</a></li>
<li><a href="http://bitovi.com/training/">Training</a></li>
<li><a href="http://bitovi.com/open-source/">Open Source</a></li>
</ul>
</li>
</ul>
<div class="brand">
<div class="logo">
<a href="../index.html" alt="CanJS"></a>
</div>
</div>
<ul class="top-right-links">
<li>
<a href="https://gitter.im/canjs/canjs">Chat</a>
</li>
<li>
<a href="http://forums.donejs.com/c/canjs">Forum</a>
</li>
<li>
<a class="github-button nav-social" href="https://github.com/canjs/canjs" data-count-href="/canjs/canjs/stargazers" data-count-api="/repos/canjs/canjs#stargazers_count">Star</a>
</li>
<li>
<a href="https://twitter.com/canjs" class="twitter-follow-button nav-social" data-show-count="true" data-show-screen-name="false">Follow @canjs</a><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</li>
</ul>
</div>
<div class="breadcrumb">
<li><a href="../index.html">CanJS</a></li> /
<li><a href="guides.html">Guides</a></li> /
<li><a href="migrate-3.html">Migrating to 3.0</a></li>
<li class="breadcrumb-dropdown">/ <a> On this page</a>
<ul class="on-this-page"></ul>
</li>
<div class="nav-toggle" title="Back to top"></div>
</div>
</div>
<div class="bottom-right">
<article>
<section class="title">
<div class="page-type">
<h1>Migrating to 3.0</h1>
<div>page</div>
</div>
<section class="description">
</section>
</section>
<section class="on-this-page-table">
</section>
<section class="title-footer">
<ul class="title-links">
<!-- <li><a href="#">docco</a></li> -->
<li><a href="//github.com/canjs/canjs/tree/v3.0.0/docs/can-guides/commitment/migrating_to_3.0.md">source</a></li>
<!-- <li><a href="#">download</a></li> -->
<!-- <li><a href="#">tests</a></li> -->
</ul>
</section>
<section class="body">
<p>CanJS 3.0 introduces a new even more modular project structure and several new features, while having a minimal number of deprecations or removals to the existing 2.3 API.</p>
<p>This guide goes over:</p>
<ul>
<li>How to install CanJS 3.0 and how that differs from in the past.</li>
<li>The <em>minimal migration path</em>. The steps that are required in order to upgrade from 2.x to 3.0 with the fewest number of code changes.</li>
<li>A second migration path with more modern conventions (such as the use of NPM packages).</li>
<li>The future proof path using all of the modern libraries we are most excited about (such as <a href="can-define.html" title="Exports the define method that defines observable properties and their behavior on a prototype object.">can-define</a>).</li>
</ul>
<h2>Getting CanJS 3.0</h2>
<p>The recommended way to install CanJS 3.0 is through <a href="https://www.npmjs.com/">npm</a>. If you are already using the <a href="https://www.npmjs.com/package/can">can package</a> you can continue to do so, but we recommend installing the specific dependencies that you need.</p>
<h3>Using can</h3>
<p>If you haven't installed CanJS through npm in the past please skip to the next section and install the can-* packages.</p>
<p>If you are already using <code>can</code> through npm just change the version in your <code>package.json</code> to 3.0:</p>
<pre><code class="language-js">{
...
"dependencies": {
"can": "^3.0.0"
}
}
</code></pre>
<p>Using the <em>^</em> ensures you get minor and patch releases as those are released.</p>
<h3>Using can-*</h3>
<p>Better than installing the <code>can</code> package is to install just the packages that you are using in your application. For example, if you are using <a href="can-component.html" title="Create a custom element that can be used to manage widgets or application logic.">can-component</a> you can install it with:</p>
<pre><code class="language-js">npm install can-component --save
</code></pre>
<p>A full list of the available packages are shown the <a href="http://canjs.github.io/canjs/">homepage</a>.</p>
<h2>Minimal migration path</h2>
<p>At minimum, to upgrade to 3.0, you must make all of the below changes to your code:</p>
<h3>Use can/legacy</h3>
<p>In your code where you normally would import <code>can</code>, instead import <code>can/legacy</code>:</p>
<pre><code class="language-js">var can = require("can/legacy");
</code></pre>
<p>This will give you a <code>can</code> object with <em>most</em> of the same APIs as in 2.3 with the exception of:</p>
<ul>
<li>[can-mustache] is not included with can/legacy but can still be installed as a separate package.</li>
<li>The former <code>can.view</code> functionality no longer exists, see below.</li>
</ul>
<h3>Set leakScope on Components</h3>
<p>In CanJS 2.2 we introduced <a href="can-component.prototype.leakScope.html" title="Allow reading the outer scope values from a component's template and a component's viewModel values in the user content.">leakScope: false</a> as a property on a <a href="can-component.html" title="Create a custom element that can be used to manage widgets or application logic.">can-component</a>. This prevents values in parent templates from leaking into your Component's template. In 3.0 <strong>leakScope</strong> is now false by default.</p>
<p>If you have a [can-component.prototype.template] like:</p>
<pre><code><some-component></some-component>
</code></pre>
<p>That you render with a <a href="can-map.html" title="Create observable objects.">map</a> containing a <code>page</code> property like so:</p>
<pre><code class="language-js">render(new Map({
page: "home"
}));
</code></pre>
<p>This <code>page</code> property is not available within some-component's own template.</p>
<p>If the component's template looks like:</p>
<pre><code><h1>Hello {{page}}</h1>
</code></pre>
<p>It can only look-up the <code>page</code> property on some-component's own <a href="can-component.prototype.ViewModel.html" title="Provides or describes a constructor function that provides values and methods
to the component's template. The constructor function
is initialized with values specified by the component element's data bindings.">ViewModel</a>. To restore the behavior in 2.x, simply set <a href="can-component.prototype.leakScope.html" title="Allow reading the outer scope values from a component's template and a component's viewModel values in the user content.">leakScope</a> to be <code>true</code> on the Component:</p>
<pre><code class="language-js">Component.extend({
tag: "some-component",
ViewModel: ...,
leakScope: true
});
</code></pre>
<h3>Asynchronous inserted/removed events</h3>
<p>In your <a href="can-component.html" title="Create a custom element that can be used to manage widgets or application logic.">can-component</a>s, the <a href="can-util/dom/events/inserted/inserted.html" title="This event fires when the bound element is added to the DOM.">inserted</a> and <a href="can-util/dom/events/removed/removed.html" title="This event fires when the bound element is detached or destroyed.">removed</a> events were previously fired synchronously as the element was inserted into the DOM. To improve performance these events are now fired async.</p>
<p>There is now a <a href="can-component/beforeremove.html" title="An event called only on component's elements before they are removed from the
document if live binding is performing the removal. It can be listened to
within a component's can-component.prototype.events object or on a component
element with can-stache-bindings.event bindings. This is an additional
special event only on component elements. inserted
and removed events are available on all elements.">beforeremove</a> event that fires synchronously in case you need to perform memory cleanup. For example you might need to access the parent's viewModel:</p>
<pre><code class="language-js">Component.extend({
tag: "my-panel",
events: {
"beforeremove": function(){
canViewModel(this.element.parentNode).removePanel(this.viewModel);
}
}
}
</code></pre>
<h3>can.view is no more</h3>
<p>The <code>can.view</code> methods have been removed in 3.0. The most common use was to create a template renderer from a script element with the page. Instead of:</p>
<pre><code class="language-js">var render = can.view('some-id');
</code></pre>
<p>Just use the DOM APIs and pass the string directly into <a href="can-stache.html" title="Live binding Mustache and Handlebars-compatible templates.">can-stache</a>:</p>
<pre><code class="language-js">var templateString = document.getElementById('some-id').innerHTML;
var render = stache(templateString);
</code></pre>
<p>If you were using <code>can.view.preload</code> then use <a href="can-stache.registerPartial.html" title="Register a partial.
Register a partial template that can be rendered with can-stache.tags.partial.">registerPartial</a> instead.</p>
<pre><code class="language-js">stache.registerPartial("some-id", renderer);
</code></pre>
<h3>Promises are needed</h3>
<p>Native <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a> are used instead of jQuery promises which means you need to:</p>
<ul>
<li>Include a Promise polyfill if targeting browsers that do not have native support. <a href="http://stealjs.com/">Steal</a> includes a polyfill for you.</li>
<li>Instead of <code>.fail()</code> use <code>.catch()</code>.</li>
<li>Instead of <code>.done()</code> use <code>.then()</code>.</li>
<li>Only a single a value is returned from a native Promise.</li>
</ul>
<h3>Passing the "this" value within each helper</h3>
<p>When passing the <code>this</code> value to a <a href="can-stache.Helpers.html" title="Helpers are functions that can be registered and called from within templates. These functions
are typically used to provide functionality that is more appropriate for
the view than the viewModel.">helper</a> like:</p>
<pre><code>{{helper .}}
</code></pre>
<p>in <a href="can-stache.html" title="Live binding Mustache and Handlebars-compatible templates.">can-stache</a> this now passes a <a href="can-compute.html" title="Create an observable value.">can-compute</a> to the helper.</p>
<p>You can fix this either by having your helpers handle computes, or using <a href="can-stache/expressions/call.html" title="">call expressions</a> instead:</p>
<pre><code>{{helper(.)}}
</code></pre>
<h3>No more global scope names</h3>
<p>Most recently-built applications do not depend on adding to the global namespace, but in case you have code that does:</p>
<pre><code class="language-js">Construct.extend("foo.bar", ...)
</code></pre>
<p>Which sets <code>window.foo.bar</code>, this argument is no longer accepted by <a href="can-construct.html" title="Provides a way to easily use the power of prototypal inheritance
without worrying about hooking up all the particulars yourself. Use
can-construct.extend to create an inheritable
constructor function of your own.">can-construct</a>. If you <em>really</em> need to set a global you can do so yourself using the return value of <a href="can-construct.extend.html" title="">extend</a>.</p>
<p>Instead the first argument to <a href="can-construct.extend.html" title="">extend</a> is the name of the constructor function. This is nice for development as you'll get named objects in your dev tools.</p>
<h2>Modernized migration path</h2>
<p>In addition to the above, to set your project up to more easily be able to upgrade in the future you can take the following measures:</p>
<h3>Use can-* packages</h3>
<p>As mentioned earlier in the guide, CanJS 3.0 is divided into separate npm packages. This allows us to more quickly updating parts of CanJS without affecting other functionality. You can take advantage of this by installing the individual can-* packages and using them directly.</p>
<p>You might be using <a href="can-component.html" title="Create a custom element that can be used to manage widgets or application logic.">can-component</a> like either:</p>
<pre><code class="language-js">var can = require("can");
can.Component.extend({ ... });
</code></pre>
<p>or</p>
<pre><code class="language-js">var Component = require("can/component/component");
Component.extend({ ... });
</code></pre>
<p>Which you are using, update your code to instead look like:</p>
<pre><code class="language-js">var Component = require("can-component");
Component.extend({ ... });
</code></pre>
<p>Use the same pattern for the other can modules you are using. In general you should not be using the <code>can.</code> properties any more, but rather importing (through your module loader / bundler) only the packages and modules that you are using.</p>
<h3>Wrap elements in jQuery objects</h3>
<p>If you are using <a href="can-jquery/legacy.html" title="Enables legacy integrations between CanJS and jQuery.
Importing can/jquery/legacy will return the jQuery object. It will also import can-jquery so that the event system hooks are set up.
Additionally it will force element callbacks (such as those in can-control) to be jQuery wrapped.
var $ = require("can-jquery/legacy");">can-jquery/legacy</a> to get automatically jQuery-wrapped elements in <a href="can-control.html" title="Create organized, memory-leak free, rapidly performing, stateful controls with declarative event binding. Use Control to create UI
controls like tabs, grids, and context menus,
and organize them into higher-order business rules with
can.route. It can serve as both a traditional view and a traditional controller.">can-control</a> event handlers, you'll want to remove the usage of <a href="can-jquery/legacy.html" title="Enables legacy integrations between CanJS and jQuery.
Importing can/jquery/legacy will return the jQuery object. It will also import can-jquery so that the event system hooks are set up.
Additionally it will force element callbacks (such as those in can-control) to be jQuery wrapped.
var $ = require("can-jquery/legacy");">can-jquery/legacy</a> as it doesn't play well with <a href="can-component.html" title="Create a custom element that can be used to manage widgets or application logic.">can-component</a>s that do not expect elements to be jQuery-wrapped.</p>
<p>Instead use <a href="can-jquery.html" title="Extensions to the event system so that can events and jQuery events are cross-bound.
Importing can-jquery will return the jQuery object and wire up the event system.
var $ = require("can-jquery");
var div = $("<div>");
div.on("inserted", function(){
// it inserted!
});
$("body").append(div);">can-jquery</a> directly and handle the wrapping yourself. For example:</p>
<pre><code class="language-js">var Component = require("can-component");
var $ = require("can-jquery");
Component.extend({
tag: "some-component",
events: {
inserted: function(){
this.element = $(this.element);
},
"li click": function(li){
var $li = $(li);
}
}
});
</code></pre>
<p><a href="can-jquery.html" title="Extensions to the event system so that can events and jQuery events are cross-bound.
Importing can-jquery will return the jQuery object and wire up the event system.
var $ = require("can-jquery");
var div = $("<div>");
div.on("inserted", function(){
// it inserted!
});
$("body").append(div);">can-jquery</a> will continue to be supported indefinitely but <a href="can-jquery/legacy.html" title="Enables legacy integrations between CanJS and jQuery.
Importing can/jquery/legacy will return the jQuery object. It will also import can-jquery so that the event system hooks are set up.
Additionally it will force element callbacks (such as those in can-control) to be jQuery wrapped.
var $ = require("can-jquery/legacy");">can-jquery/legacy</a> will be dropped in a future major version.</p>
<h3>Remove use of "change" events</h3>
<p>When you upgrade to use <a href="can-define.html" title="Exports the define method that defines observable properties and their behavior on a prototype object.">can-define</a> you'll no longer receive "change" events on maps. If you had any code that binded on a map's "change" event, you'll want to instead bind to the properties that you are interested in. For example:</p>
<pre><code class="language-js">route.bind("change", function(){
// The route changed
});
</code></pre>
<p>Can be modified to instead use a compute that calls <code>serialize</code> on the route's map:</p>
<pre><code class="language-js">var routeMap = compute(function(){
return route.map.serialize();
});
routeMap.bind("change", function(){
A property on the route's map changed.
});
</code></pre>
<p>As you might notice, we are also favoring using <a href="can-event.on.html" title="can-event.on">on()</a> rather than <code>bind()</code> now (although bind() still work the same).</p>
<h2>Future-proof migration path</h2>
<p>In addition to the steps taken in the two above section, if you <em>really</em> want to stay ahead of the curve, make the following changes to your application:</p>
<h3>can-define replaces can-map</h3>
<p>If you've used <a href="can-map-define.html" title="Defines the
type, initial value, get, set, remove, and serialize behavior for attributes
of a Map.">can-map-define</a> in the past then using <a href="can-define.html" title="Exports the define method that defines observable properties and their behavior on a prototype object.">can-define</a> should be familiar to you. Using <a href="can-define/map/map.html" title="Create observable objects.">can-define/map/map</a> is the easiest migration path and is what we show in all of the examples in CanJS 3.0's docs.</p>
<p>A typical map looks like:</p>
<pre><code class="language-js">var Map = require("can-map");
require("can-map-define");
var CarOwner = Map.extend({
define: {
cars: {
Type: Car.List
},
favorite: {
Type: Car
},
color: {
type: "string"
},
age: {
value: 18
}
}
});
</code></pre>
<p>Which can be replaced by flattening it into a <a href="can-define/map/map.html" title="Create observable objects.">can-define/map/map</a> like so:</p>
<pre><code class="language-js">var DefineMap = require("can-define/map/map");
var CarOwner = DefineMap.extend({
cars: CarList,
favorite: Car,
color: "string",
age: {
type: "number",
value: 18
}
});
</code></pre>
<p>Using <a href="can-define.html" title="Exports the define method that defines observable properties and their behavior on a prototype object.">can-define</a> allows you to use maps without the <a href="can-map.prototype.attr.html" title="Get or set properties on a Map.">.attr()</a> method that's needed in <a href="can-map.html" title="Create observable objects.">can-map</a> and <a href="can-list.html" title="">can-list</a>. To use this with DefineMap just use the dot operator instead:</p>
<pre><code class="language-js">var carOwner = new CarOwner();
// This is observable!
carOwner.favorite = new Car({ type: "Toyota" });
</code></pre>
<h3>Use can-connect directly</h3>
<p>When using the easy migration path you were secretly using <a href="can-connect/can/model/model.html" title="Exports a constructor that works very similar to can.Model.">can-connect/can/model/model</a>, a constructor that is mostly backwards compatible with [can-model].</p>
<p>Most new projects should use can-connect directly, and <a href="can-connect/can/super-map/super-map.html" title="Create connection with many of the best behaviors in can-connect and hook it up to
a map.">can-connect/can/super-map/super-map</a> is the easiest way to create models with connect's features. Using can-connect directly allows you to use <a href="can-define/map/map.html" title="Create observable objects.">can-define/map/map</a>s as your models like so:</p>
<pre><code class="language-js">var DefineMap = require("can-define/map/map");
var DefineList = require("can-define/list/list");
var superMap = require("can-connect/can/super-map/super-map");
var Message = DefineMap.extend({
id: "*"
});
Message.List = DefineList.extend({
"#": Message
});
var messageConnection = superMap({
url: 'http://chat.donejs.com/api/messages',
idProp: 'id',
Map: Message,
List: Message.List,
name: 'message'
});
</code></pre>
<h3>Update use of binding syntax</h3>
<p>In 2.3 we introduced new binding syntaxes. In 3.0 there are available with <a href="can-stache-bindings.html" title="Provides template event, one-way, and two-way bindings.">can-stache-bindings</a>. Although the old binding syntaxes still work, they will likely be dropped in 4.0. View can-stache-binding's documentation to learn how to use the new bindings.</p>
<p>An example is changing a can-value binding from:</p>
<pre><code><input type="text" can-value="{someProp}" />
</code></pre>
<p>To:</p>
<pre><code><input type="text" {($value})="someProp" />
</code></pre>
<p>3.0 also introduces new <a href="can-stache.registerConverter.html" title="Register a helper for bidirectional value conversion.">stache converters</a> which are a special type of <a href="can-stache.Helpers.html" title="Helpers are functions that can be registered and called from within templates. These functions
are typically used to provide functionality that is more appropriate for
the view than the viewModel.">helper</a> that works two-way to update an element when an observable value changes, and also update the observable value when the form element's value changes (from user input).</p>
<p>An example is the [can-stache-bindings.converters.string-to-any] converter which converts a primitive value to a string to set a <code><select></code>'s value, and then converts the <code><select></code> value when a user selects an <code><option></code> back to the primitive value to update the scope value:</p>
<pre><code><select {($value)}="string-to-any(~favePlayer)">
<option value="23">Michael Jordan</option>
<option value="32">Magic Johnson</option>
</select>
</code></pre>
</section>
<script type="text/javascript">
var docObject = {"src":{"path":"docs/can-guides/commitment/migrating_to_3.0.md"},"description":"\n","name":"migrate-3","title":"Migrating to 3.0","type":"page","parent":"guides/commitment","order":2,"comment":" ","pathToRoot":".."};
</script>
</article>
<footer><p>CanJS is part of <a href="http://donejs.com" target="_blank">DoneJS</a>. Created and maintained by the core <a href="https://donejs.com/About.html#section=section_Team" target="_blank">DoneJS team</a> and <a href="http://bitovi.com" target="_blank">Bitovi</a>. <strong>Currently 3.0.0.</strong></p></footer>
</div>
</div>
</div>
<script>
steal = {
instantiated: {
"bundles/bit-docs-site/static.css!$css" : null
}
};
</script>
<script type='text/javascript' data-main="bit-docs-site/static" src="./static/node_modules/steal/steal.production.js"></script>
<script async defer src="https://buttons.github.io/buttons.js"></script>
</body>
</html>