1.0から1.2へのアップグレード

AngularJSのバージョン1.2では、幾つかの破壊的な変更が導入されました。 そのため、既存のアプリケーションのソースコードを変更することが必須かもしれません。

我々は破壊的な変更を避けようとしましたが、幾つかのケースでそれは不可能でした。 AngularJS1.2でのこれらの変更では、デフォルトでも安全なアプリケーションであるために受けた徹底したレビューも含まれます。 幾つかの新しい機能特にアニメーションでは、多少の変更無くして実現するのは不可能でした。 最後に目立つバグは既存のAPIを変更することで最善な形でフィックスされました。

注意: AngularJSバージョン1.1.xは、破壊的な変更とマイナーリリースの間の"実験的"なバージョンとみなされています。 バージョン1.2は1.1のブランチの幾つかのバージョンの結果で、ステーブルなAPIを持ちます。 もし、1.1のアプリケーションがあり、1.2に移行したいと考えているのであれば、 下記のガイドの内容の全てを適用すべきですが、 同様にchangelogの確認も必要になるかもしれません。

ngRouteはモジュールへ移動

ngResourceと同様、ngRouteは独自のモジュールになりました。

$route、ngViewと/または$routeParamsを使用するアプリケーションは、現在angular-route.jsファイルを読み込み、 アプリケーションのモジュールはngRouteモジュールへの依存を持つ必要があります。

Before:

angular-route.js
var myApp = angular.module('myApp', ['someOtherModule']);

After:

<script src="angular.js"></script>
<script src="angular-route.js"></script>
var myApp = angular.module('myApp', ['ngRoute', 'someOtherModule']);

5599b55参照

テンプレートは自動的にpromiseをラップしなくなりました

$parseとテンプレートは、自動的にpromiseをラップしなくなりました。

Before:

$scope.foo = $http({method: 'GET', url: '/someUrl'});
<p>{{foo}}</p>

After:

$http({method: 'GET', url: '/someUrl'})
  .success(function(data) {
    $scope.foo = data;
  });
<p>{{foo}}</p>

この機能は非推奨になりました。 もしどうしても必要な場合は、$parseProvider.unwrapPromises(true)のAPIを通して描画することが可能です。

5dc35b52b6a37d11参照

名前付きのワイルドカードの構文は$routeに変更

コードの移行にあたり、下記の例に従ってください。 *highlightは、:highlight*になります。

Before:

$routeProvider.when('/Book1/:book/Chapter/:chapter/*highlight/edit',
          {controller: noop, templateUrl: 'Chapter.html'});

After:

$routeProvider.when('/Book1/:book/Chapter/:chapter/:highlight*/edit',
        {controller: noop, templateUrl: 'Chapter.html'});

04cebcc1参照

[src]または[ng-src]に1つだけ式をバインドすることが可能です

<a>と<img>要素を除き、要素のsrc属性に複数の式をバインドする事は出来ません。

これはAngular1.2による、セキュリティ向上のための導入の1つです。

式の連結は、連結されたことによる組み合わせで、安全では無い使われ方がされているか、潜在的なXSS脆弱性がないか、 といった事を分かりにくくします。 XSS検査のタスクをシンプルにするために、iframe[src]、object[src]のような要素の*[src/ng-src]へのバインディングに使用される式は、 1つだけ式が使用される必要があるようにしました。

<img src="{{a}}/{{b}}"> OK(imgは対象外)
<iframe src="{{a}}/{{b}}"</iframe> NG
<iframe src="{{a}}"></iframe> OK

コードを移行するのにあたり、スコープにメソッドを割り当てて、それを使用することで複数の式を組み合わせてください。

Before:

scope.baseUrl = 'page';
scope.a = 1;
scope.b = 2;
<!-- Are a and b properly escaped here? Is baseUrl controlled by user? -->
<iframe src="{{baseUrl}}?a={{a}&b={{b}}">

After:

var baseUrl = "page";
scope.getIframeSrc = function() {

  // One should think about their particular case and sanitize accordingly
  var qs = ["a", "b"].map(function(value, name) {
      return encodeURIComponent(name) + "=" +
             encodeURIComponent(value);
    }).join("&");

  // `baseUrl` isn't exposed to a user's control, so we don't have to worry about escaping it.
  return baseUrl + "?" + qs;
};
<iframe src="{{getIframeSrc()}}">

38deedd6参照

DOMイベントハンドラの内部補間は禁止になりました

DOMイベントハンドラは任意のJavaScriptコードを実行します。 ハンドラのようなものに補完を使用することは、補完値は評価されるJS文字列になるという事を意味します。 そのような文字列を格納または生成することは、エラーになり易く、XSS脆弱性発生の原因にもなりえます。 一方、ngClickと他のAngular独自のイベントハンドラは、 安全なwindow外(スコープ内)のコンテキストでAngular式を評価します。

コードを移行するにあたり、下記の例を参考に従ってください。

Before:

JS:   scope.foo = 'alert(1)';
HTML: <div onclick="{{foo}}">

After:

JS:   scope.foo = function() { alert(1); }
HTML: <div ng-click="foo()">

39841f2e参照

ディレクティブの最後に-startまたは-endを付けられません

この変更は複数要素ディレクティブを有効にするために必要でした。 最良の修正は、彼らがこれらの接尾辞で終わらないように、既存のディレクティブ名を変更することです。

e46100f7参照

$q内のpromise.alwaysは、promise.finallyに名前変更されました

Q promiseライブラリに$qが揃えられましたが、 この変更により、IE8のような非ES5ブラウザで使用することが少し困難になってしまいました。

最終的に、最近では$qに追加されたcatchのAPIと一緒に使われ、 それはDOMのpromise標準の一部になっています。(翻訳に自信なし)

下記の例に従って、コードの移行を行ってください。

Before:

$http.get('/foo').always(doSomething);

After:

$http.get('/foo').finally(doSomething);

また、IE8互換のコードの場合

$http.get('/foo')['finally'](doSomething);

f078762d参照

ngMobileはngTouchになりました

タッチ可能なデバイスがモバイルデバイスであるとは限らないため、このモジュールのより適切な名前に変更することにしました。

移行するには、全てのngMobileの参照をngTouchに、angular-mobile.jsをangular-touch.jsに置き換えてください。

94ec84es参照

Resource.$thenは削除されました

Resourceインスタンスは、$then関数を持たなくなります。 代わりに$promise.thenを使用してください。

Before:

Resource.query().$then(callback);

After:

Resource.query().$promise.then(callback);

94ec84e7参照

Resourceメソッドはpromiseを返すようになりました

Resourceインスタンスのメソッドは自身のインスタンスでは無く、promiseを返すようになりました。

Before:

resource.$save().chaining = true;

After:

resource.$save();
resource.chaining = true;

05772e15参照

ResourceのpromisesはResourceのインスタンスでresolveします

successの場合、HTTPレスポンスオブジェクトでは無く、 ResourceインスタンスでResourceのpromiseはresolveされます。

インターセプターAPIを使用して、HTTPレスポンスオブジェクトにアクセスします。

Before:

Resource.query().$then(function(response) {...});

After:

var Resource = $resource('/url', {}, {
  get: {
    method: 'get',
    interceptor: {
      response: function(response) {
        // expose response
        return response;
      }
    }
  }
});

05772e15参照

$location.searchは複数キーをサポートします

$location.searchは、 提供される配列に格納された同じ値による複数キーをサポートするようになりました。
この変更以前は、

  • parseKeyValueは最後のキーのみを取得し、その前の全てのキーを上書きしていました。
  • toKeyValueはカンマ区切りの文字列でキーに追加されていました。

これはバグを誘発しやすい振る舞いでした。 もし、サーバがこの振る舞いをあてにしているのであれば、サーバ側を修正するか、 単純な配列のシリアライズを、$locationに渡される前にクライアント側で行うようにすべきです。

80739409参照

ngBindHtmlUnsafeは削除され、ngBindHtmlに置き換えられました

ngBindHtmlは、ngSanitizeモジュールからコアであるngモジュールへ移されました。

ngBindHtmlは、$sce.trustAsHtml(string)の結果にバインドされた際に、 ngBindHtmlUnsafeのような振る舞いを提供します。 (式を評価し、その結果をinnerHTMLでDOMへ) プレーンな文字列がバインドされた際に、文字列はinnerHTMLされる前に$sanitizeを介して文字列がサニタイズされます。 もし、$sanitizeサービスが利用可能では無い場合(ngSanitizeが読み込まれない)、 バインドされた式は信頼出来ない値として評価され、例外がスローされます。

dae69473参照

フォーム名の式は評価されます

もし、フォームが名前を持っていれば、式として評価されます。

<form name="ctrl.form">

コントローラーからフォームにアクセスしているのであれば、

Before:

function($scope) {
  $scope['ctrl.form'] // form controller instance
}

After:

function($scope) {
  $scope.ctrl.form // form controller instance
}

これは、新しい"コントローラーとして"の文法を使用して、コントローラーからフォームへのアクセスを可能にしてくれます。 以前の動作と比べて、特段メリットが提供されているというわけではありません。

8ea802a1参照

input名で"hasOwnProperty"と名付ける事は禁止になりました

input名が"hasOwnProperty"であるものは、フォームまたはngFormディレクティブ内部で許可されなくなりました。

以前は、名前が"hasOwnProperty"のinputは暗黙的に無視され、スコープに追加されました。 現在は、badname例外がスローされます。 input名での"hasOwnProperty"の使用は、通常では有り得ないことでバッドプラクティスでもあります。 移行に際して、このinput名を変更してください。

7a586e5参照

ディレクティブ: postLink関数の順番が逆になりました

postLink関数の順番は、現在はpreLinkとコンパイル関数に対応する順番の反対になっています。

以前は、compile/link関数は優先度によって並べられた順に実行されていました。

順番 ステップ 古い並び順 新しい並び順
1 コンパイル(Compile)関数 高い → 低い
2 子ノードをコンパイル
3 PreLink関数 高い → 低い
4 子ノードをリンク
5 PostLink関数 高い → 低い 低い → 高い

"高い"、"低い"はディレクティブの優先度を指します。

ごく少数のディレクティブに、postLink関数(コンパイル関数の順番とは異なり)の順番を当てにするものがあるため、 稀に既存ディレクティブがこの変更によって影響を受けるので、 それをpreLink関数に変換するか、負の優先順位を与える必要があるかもしれません。

このコミットの差分で、 調整されたディレクティブの属性の補完部分を確認する事が可能です。

31f190d4参照

ディレクティブの優先度

ngRepeat、ngSwitchWhen、ngIf、ngInclude、ngViewの優先度が変更されました。 これは明示的に優先順位を指定するディレクティブに影響を与える可能性があります。

ngRepeat、ngSwitchWhen、ngIf、ngInclude、ngViewは全ての共通のシナリオ内で一緒に動作するように、 下記の順序に沿って達成されるように調整されています。

ディレクティブ 古い優先度 新しい優先度
ngRepeat 1000 1000
ngSwitchWhen 500 800
ngIf 1000 600
ngInclude 1000 400
ngView 1000 400

b7af76b4参照

ngScenario

browserTriggerは現在、直接マウスイベントのためのパラメータを使用せず、代わりにeventDataオブジェクトを使用します。 移行するためには、オブジェクトの内部にキー、x、yパラメータを配置し、browserTrigger関数の第3引数としてそれを配置してください。

28f56a38参照

ngIncludeとngViewは更新でその全体の要素が置換されます

以前のngIncludeとngViewは、要素のコンテンツのみを更新していました。 現在これらのディレクティブは、新しいコンテンツが含まれる度に要素を作り直します。

これは、既に存在していてコンテンツに含まれている全ての単一のrootElementが、 はるかに簡単にアニメーションを行うためのCSSスタイルを定義することを保証します。(翻訳に自信なし)

7d69d52aaa2133ad参照

URLはホワイトリストに対してサニタイズされるようになりました

$compileProviderを介して設定されたホワイトリストは、どのURLが安全であるかを設定するのに使用することが出来ます。 デフォルトでは、mimeタイプimage/*付きのdata:URIを含む、 全ての一般的なプロトコルの接頭辞がホワイトリスト化されています。 悪意のあるイメージリンクを含まないアプリケーションは、この変更の影響を受けないべきです。

1adf29af3e39ac7e参照

隔離スコープはscopeプロパティを使用してディレクティブにのみ公開されます

隔離スコープを持たないディレクティブは、同じ要素上の隔離ディレクティブから隔離スコープを取得しません。 もし、この振る舞いに依存した(隔離されていないディレクティブが、隔離スコープを持つものにアクセスする必要がある)コードである場合、 隔離ディレクティブをローカルスコープを使用してこれらを明示的に渡すように変更してください。

Before

<input ng-model="$parent.value" ng-isolate>

.directive('ngIsolate', function() {
  return {
    scope: {},
    template: '{{value}}'
  };
});

After

<input ng-model="value" ng-isolate>

.directive('ngIsolate', function() {
  return {
    scope: {value: '=ngModel'},
    template: '{{value}}
  };
});

909cabd3#1924#2500参照

補完プロパティの変更

予め設定される補完(interpolation)の優先度は、1.2.0-rc.2では-100、1.2.0-rc.2以前は100でした。 以前は、この変更のバインディングは、postLinkフェーズで設定されていました。

現在では、属性の補完(interpolation)(のバインディング)は、優先度100のディレクティブとして実行され、 preLinkフェーズでバインディングが設定されます。

79223eae#4525#4528#4649参照

アンダースコアの接頭辞/接尾辞のプロパティはバインドされません

取り下げ:この破壊的な変更は1.2.1で取下げられたため、バージョン1.2.1かそれ以上を使用しているのであれば無視して下さい。

This change introduces the notion of "private" properties (properties whose names begin and/or end with an underscore) on the scope chain. These properties will not be available to Angular expressions (i.e. interpolation in templates and strings passed to $parse) They are freely available to JavaScript code (as before).

Motivation

Angular expressions execute in a limited context. They do not have direct access to the global scope, window, document or the Function constructor. However, they have direct access to names/properties on the scope chain. It has been a long standing best practice to keep sensitive APIs outside of the scope chain (in a closure or your controller.) That's easier said that done for two reasons:

  • JavaScript does not have a notion of private properties so if you need someone on the scope chain for JavaScript use, you also expose it to Angular expressions
  • The new controller as syntax that's now in increased usage exposes the entire controller on the scope chain greatly increaing the exposed surface.

Though Angular expressions are written and controlled by the developer, they:

  • Typically deal with user input
  • Don't get the kind of test coverage that JavaScript code would

This commit provides a way, via a naming convention, to allow restricting properties from controllers/scopes. This means Angular expressions can access only those properties that are actually needed by the expressions.

See 3d6a89e8.

select[multiple]へのバインド不可

select[single]とselect[multiple]の切り替えは、常にブラウザの癖に左右されがちで安定しないものでした。 この機能は誰も使用する事が期待出来ないため、双方向データバインディングで動作しなくなりました。

もし、あなたがこの機能を適切に追加することに興味があるのであれば、Githubにプルリクエストを送って下さい。

d87fa004参照

i18nから地域特定のローカルファイルが削除されました

AngularJSはGoogleのクロージャ(閉鎖的な?)ライブラリのロケール(locale)ファイルを使用しています。 下記のロケールは、そこから削除されたため、Angularはそれらのサポートを続けることが出来なくなりました。

chr, cy, el-polyton, en-zz, fr-rw, fr-sn, fr-td, fr-tg, haw, it-ch, ln-cg, mo, ms-bn, nl-aw, nl-be, pt-ao, pt-gw, pt-mz, pt-st, ro-md, ru-md, ru-ua, sr-cyrl-ba, sr-cyrl-me, sr-cyrl, sr-latn-ba, sr-latn-me, sr-latn, sr-rs, sv-fi, sw-ke, ta-lk, tl-ph, ur-in, zh-hans-hk, zh-hans-mo, zh-hans-sg, zh-hans, zh-hant-hk, zh-hant-mo, zh-hant-tw, zh-hant

これらのロケールは公式のAngularJSリポジトリから削除されましたが、 自身が保持するロケールファイルをコピーすることで、それを読み込んで使用を続けることが可能です。

6382e21f参照

 Back to top

© 2017 Google
Licensed under the Creative Commons Attribution License 3.0.

このページは、ページトップのリンク先のAngularJS公式ドキュメント内のページを翻訳した内容を基に構成されています。 下記の項目を確認し、必要に応じて公式のドキュメントをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。

  • AngularJSの更新頻度が高いため、元のコンテンツと比べてドキュメントの情報が古くなっている可能性があります。
  • "訳注:"などの断わりを入れた上で、日本人向けの情報やより分かり易くするための追記を行っている事があります。