私はアプリでAngularjsフレームワークをターボリンクで使用しようとしています。ページ変更後、新しいイベントリスナーは初期化されません。それを機能させる方法はありますか?前もって感謝します!
TurbolinksとAnguluarJSの両方を使用して、ユーザーへの応答という意味で、Webアプリケーションの応答を高速化できます。インタラクションは、ページ全体を再ロードおよび再レンダリングすることなく、Webページで発生します。
次の点で異なります。
AngularJSは、リッチなクライアント側アプリケーションを構築するのに役立ちます、クライアントマシンで実行される多くのJavaScriptコードを記述します。このコードにより、サイトはユーザーに対してインタラクティブになります。 JSON APIを使用して、サーバー側のバックエンド、つまりRailsアプリと通信します。
Turbolinksは、JavaScriptをコーディングすることなくサイトをインタラクティブにするのに役立ちます。これにより、サーバー側で実行されるRuby/Railsコードにスティックを固定し、「魔法のように」AJAXを使用して置き換え、再レンダリングすることができます。 、変更されたページの部分のみ。
Turbolinksが強力なAJAXメカニズムを手で何もせずに使用し、Ruby/Railsをコーディングするだけでよい場合、JavaScriptフレームワークを統合したいアプリケーションが成長する段階が来るかもしれませんAngularJSなど。
特に、AngularJSを一度に1つのコンポーネントにアプリケーションに連続的に統合したいこの中間段階では、Angular JSとTurbolinksを一緒に実行することは完全に理にかなっています。
Angularコードには、次のようなアプリケーションモジュールを定義する行があります。
# app/assets/javascripts/angular-app.js.coffee
# without turbolinks
@app = angular.module 'MyApplication', ['ngResource']
このコードは、ページがロードされるときに実行されます。ただし、Turbolinksはページの一部を置き換えるだけでページ全体の読み込みを防止するため、Turbolinksによる部分的な再読み込みの後でも、angularアプリケーションが適切に初期化(「ブートストラップ」)されるようにする必要があります。したがって、上記のモジュール宣言を次のコードに置き換えます。
# app/assets/javascripts/angular-app.js.coffee
# with turbolinks
@app = angular.module 'MyApplication', ['ngResource']
$(document).on 'turbolinks:load', ->
angular.bootstrap document.body, ['MyApplication']
チュートリアルでは、HTMLコードでng-app
属性を使用してbootstrapおよびAngularアプリを自動的に作成する方法をよく見ます。
<!-- app/views/layouts/my_layout.html.erb -->
<!-- without turbolinks -->
<html ng-app="YourApplication">
...
ただし、上記の手動bootstrapとともにこのメカニズムを使用すると、アプリケーションがbootstrapを2回実行するため、アプリケーションが停止します。
したがって、このng-app
属性を削除するだけです:
<!-- app/views/layouts/my_layout.html.erb -->
<!-- with turbolinks -->
<html>
...
ターボリンクはページのレンダリングを最適化しようとし、AngularJSの通常のブートストラップと競合します。
アプリの一部の場所でTurbolinksを使用しており、一部の部分でAngularを使用している場合。 このエレガントなソリューション:を提案します
Angleapp(ng-app = "appname"を使用する)であるページへの各リンクには、次の属性が必要です。
<a href="/myapp" data-no-turbolink>Say NO to Turbolinks</a>.
2番目-Stackoverflowで言及されているのは、page:loadイベントを処理することにより、すべてのng-appを明示的にリロード/ブートストラップすることです。ページにないものをロードしている可能性があるため、リソースを浪費していることは言うまでもありません。
私は個人的に上記のソリューションを使用しました。
それが役に立てば幸い
バグの場合
不明なエラー:[ng:btstrpd]この要素「document」で既にブートストラップされたアプリ
angular 1.2.xへのアップグレード後、以下を使用して問題を修正できます。
_angular.module('App').run(function($compile, $rootScope, $document) {
return $document.on('page:load', function() {
var body, compiled;
body = angular.element('body');
compiled = $compile(body.html())($rootScope);
return body.html(compiled);
});
});
_
以前の投稿で@natesはangular.bootstrap(document, ['YourApplication'])
をangular.bootstrap("body", ['YourApplication'])
に変更することを提案しましたが、これはコンパイルされていないコンテンツのフラッシュを引き起こします。
jquery.turbolinks プラグインは、ng-appディレクティブを介してモジュールのブートストラップをトリガーできます。手動でモジュールをbootstrap=)しようとすると、jquery.turbolinksはng:btstrpdエラーにつながる可能性があります。jquery.turbolinksはpage:load
これは、新しいページ固有の<script>
タグの実行が完了する前にトリガーできるイベントです。application.jsの外部でモジュール定義を含めると、$injector:nomod
エラーが発生する可能性があります。特定のページにのみ含まれる個別のjavascriptファイルは、data-no-turbolink
を介して特定のページへのリンクで ターボリンクを無効にする にすることができます。
次のイベントハンドラーをアプリケーションに追加します。
Coffeescript:
bootstrapAngular = ->
$('[ng-app]').each ->
module = $(this).attr('ng-app')
angular.bootstrap(this, [module])
$(document).on('page:load', bootstrapAngular)
Javascript:
function bootstrapAngular() {
$('[ng-app]').each(function() {
var module = $(this).attr('ng-app');
angular.bootstrap(this, [module]);
});
};
$(document).on('page:load', bootstrapAngular);
これにより、angularアプリケーションがTurbolinksによって各ページがロードされた後に開始されます。
Turbolinksは、クライアント側のMVCフレームワークではあまり意味がありません。 Turbolinksは、サーバーの応答から本文を除くすべてを取り除くために使用されます。クライアント側のMVCでは、HTMLではなくJSONをクライアントに渡すだけです。
いずれにしても、ターボリンクは独自のコールバックを作成します。
page:load
page:fetch
page:restore
page:change
すばらしい回答を得るには、@ fiedlに+1してください。しかし、私の好みはpage:change
page:load
これはある程度の柔軟性を提供するためです。DOMはpage:load
ターボリンク以外のソースからのイベントなので、同じコールバックを起動したくない場合があります。
page:change
、その後 a page:load
は、コールバックの動作を、ターボリンクによって引き起こされたイベントのみに制限する必要があります。
function boostrapAngularJS () {
angular.bootstrap(document.body, ['My Application']);
addCallbackToPageChange();
}
function addCallbackToPageChange() {
angular.element(document).one('page:change', function () {
angular.element(this).one('page:load', boostrapAngularJS);
});
}
addCallbackToPageChange();
(これにより、ng-app
html内の宣言。AngularJSを使用する場合は通常どおり。
Turbolinksは自動的にページを取得し、その
<body>
にスワップし、<head>
をマージします。すべてのページをロードするコストは発生しません。
https://github.com/turbolinks/turbolinks#turbolinks
そのため、ng-app
要素に<html>
ディレクティブを追加する代わりに、<body>
要素に追加できます。
<html>
<body ng-app=“yourApplicationModuleName">
</body>
</html>
私が見たコメントに基づいて、AngularがTurbolinksと競合するような方法で両方を一緒に使用するための唯一の有効なシナリオ(たとえば、Angular =ルーティングの一部を処理するため)は、Angularに移植しようとしている既存のアプリケーションがある場合です。
個人的に、これをゼロから行う場合、最善の解決策はルーティングを処理するものを決定し、それに従うことだと思います。 Angularの場合、Turbolinksを削除するよりも、シングルページアプリに近いものがあれば、それはあまり役に立ちません。 Rails=ルーティングの処理を許可する場合は、Angular=を使用して、サーバーで処理できないクライアント側の動作を整理します。テンプレート。
ここにシナリオがありませんか?大規模なアプリケーションであっても、異なるフレームワーク間でルーティングの責任を分割しようとするのはエレガントではないようです... TurbolinksがAngular更新以外に干渉する他のシナリオはありますかページまたは新しいルートに移動しますか?