I am trying to use Angularjs framework in my app with turbolinks. After page change it do not initialize new eventlisteners. Is it any way to make it work? Thanks in advance!
相关问题
- Question marks after images and js/css files in ra
- Using :remote => true with hover event
- angularJS: ui-router equivalent to $location.searc
- Separate AngularJS Controllers Into Separate Files
- Eager-loading association count with Arel (Rails 3
相关文章
- Right way to deploy Rails + Puma + Postgres app to
- Passing variable through URL with angular js
- AWS S3 in rails - how to set the s3_signature_vers
- how to call a active record named scope with a str
- How to add a JSON column in MySQL with Rails 5 Mig
- “No explicit conversion of Symbol into String” for
- form_for wrong number of arguments in rails 4
- Rspec controller error expecting <“index”> but
Turbolinks doesn't quite make sense with an client side MVC framework. Turbolinks is used to to strip out the all but the body from server response. With client-side MVC you should just be passing JSON to the client, not HTML.
In any event, turbolinks creates its own callbacks.
The jquery.turbolinks plugin can trigger bootstrapping of modules via ng-app directives. If you're trying to manually bootstrap your modules, jquery.turbolinks can lead to ng:btstrpd errors. One caveat I've found is that jquery.turbolinks relies on the
page:load
event, which can trigger before any new page-specific<script>
tags finish running. This can lead to$injector:nomod
errors if you include module definitions outside of the application.js. If you really want your modules defined in separate javascript files that are only included on certain pages, you could just disable turbolinks on any links to those specific pages viadata-no-turbolink
.AngularJS vs. Turbolinks
Turbolinks as well as AnguluarJS can both be used to make a web application respond faster, in the sense that in response to a user interaction something happens on the web page without reloading and rerendering the whole page.
They differ in the following regard:
AngularJS helps you to build a rich client-side application, where you write a lot of JavaScript code that runs on the client machine. This code makes the site interactive to the user. It communicates with the server-side backend, i.e. with the Rails app, using a JSON API.
Turbolinks, on the other hand, helps to to make the site interactive without requiring you to code JavaScript. It allows you to stick to the Ruby/Rails code run on the server-side and still, "magically", use AJAX to replace, and therefore rerender, only the parts of the page that have changed.
Where Turbolinks is strong in allowing you use this powerful AJAX mechanism without doing anything by hand and just code Ruby/Rails, there might come a stage, as your application grows, where you would like to integrate a JavaScript framework such as AngularJS.
Especially in this intermedium stage, where you would like to successively integrate AngularJS into your application, one component at a time, it can make perfectly sense to run Angular JS and Turbolinks together.
How to use AngularJS and Turbolinks together
Use callback to manually bootstrap Angular
In your Angular code, you have a line defining your application module, something like this:
This code is run when the page is loaded. But since Turbolinks just replaces a part of the page and prevents an entire page load, you have to make sure, the angular application is properly initialized ("bootstrapped"), even after such partial reloads done by Turbolinks. Thus, replace the above module declaration by the following code:
Don't bootstrap automatically
You often see in tutorials how to bootstrap an Angular app automatically by using the
ng-app
attribute in your HTML code.But using this mechanism together with the manual bootstrap shown above would cause the application to bootstrap twice and, therefore, would brake the application.
Thus, just remove this
ng-app
attribute:Further Reading
Based on the comments I've seen, the only valid scenario for using both together in a way where Angular would conflict with Turbolinks (such as where I allow Angular to handle some of the routing) is if I have an existing application that I'm trying to port to Angular.
Personally, if I were to do this from scratch, I think the best solution would be to decide what should handle the routing and stick with that. If Angular, than get rid of Turbolinks -> it won't do much for you if you have something close to a single-page app. If you allow Rails to handle the routing, then just use Angular to organize client-side behavior that can't be processed by the server when serving up the templates.
Am I missing a scenario, here? It doesn't seem elegant to me to try to split the routing responsibilities between different frameworks, even in a large application... Is there some other scenario where Turbolinks would interfere with Angular other than refreshing the page or navigating to a new route?
Turbolinks attempt to optimize rendering of pages and would conflict with normal bootstraping of AngularJS.
If you are using Turbolinks in some places of your app and some parts use Angular. I propose this elegant solution:
Each link to a page that is angularapp (where you use ng-app="appname") should have this attribute:
The second - mentioned on Stackoverflow is explicitly reloading/bootstrapping every ng-app by handling page:load event. I would that's intrusive, not to mention you're potentially loading something that isn't on a page hence wasting resources.
I've personally used the above solution.
Hope it helps
Using Turbolinks and AngularJS together
+1 to @fiedl for a great answer. But my preference is to make use of
page:change
in concert withpage:load
because this affords some flexibility: the DOM can receive apage:load
event from sources other than turbolinks, so you might not want to have the same callback fire.Watching for a
page:change
, then apage:load
should restrict your callback behaviour to solely turbolinks-instigated events.(This will allow/require you to keep your
ng-app
declaration in your html, as normal when working with AngularJS.)