Building an Angular application, I'm a fan of using ng-controller and custom directives to structure the app, e.g.:
<nav ng-controller="NavController"></nav>
<date-picker></date-picker>
I like these patterns because they're declarative, and really easy to follow - you know exactly where to look to find the supporting logic.
On the other hand, using ng-view, or even the ui-router plugin (to my mind) abstracts away some of the functionality and makes it harder to read.
However, my preferred pattern gives me a problem when it comes to responding to URL changes app-wide in a logical way. I would like each part of the UI to respond appropriately to URL changes, but I don't know where to put the code. I have assumed I have two options:
I can't quite figure out how to do either.
Option one gives me complete control, but I'm unable to take advantage of ng-route - parsing parameters, etc. I'd really have to roll my own when it comes to inspecting URL changes.
With option two, I can't reference any of my controllers, because they've been declared already!
More broadly, my concern is that not finding a solution to this right away suggests that I must be thinking about things incorrectly. Is this fundamentally wrong?
EDIT: For the avoidance of doubt, I very much AM talking about an SPA, and more specifically, this is the sort of thing I'm trying to do:
<nav ng-controller="NavController"><!-- more HTML here --></nav>
<div ng-controller="VideoController"><!-- more HTML here --></div>
<div ng-controller="CommentController" ng-show="Active"><!-- more HTML here --></div>
Now, suppose I navigate to: "/video/:key/" - I want the VideoController to pick up the video key, and do what it needs to do to load a video. I want the NavController to highlight which menu item is active, etc.
If I navigate to "/video/:videokey/comment" - I want the VideoController to load a video, AND the NavController to highlight which is active, AND the CommentController to load comments / appear into video, etc.
It's this idea I haven't got my head around - responding to a URL change in TWO controllers, each responsible for a separate part of the UI in a Single Page Application.
This isn't the answer you're looking for, but it is the answer that (IMO) you need to hear.
Opinions away!
You'll spend a lot of time building the SPA around your own layout and routing ideas. It wouldn't surprise me if this were possible - if you emit events on the appropriate scope and have child controllers listen for state change events, you can define different controllers that respond differently to state changes, showing and hiding their contents, and updating those contents to reflect the current object model (/things/1 to things/2 to things/2/edit or whatever).
This is pretty much how ui-router works already, except that instead of embedding the top-level html content in the main pages it uses ui-view directives which basically handle partials and controllers.
At the end of the day, doing this, you'll have reproduced about 50% of what ui-router currently does. If you're lucky, it will work as well as ui-router. If you're not, it'll be buggy in funny ways.
What you'll have is a huuuuuge single page application which will be very difficult to debug. If you have everything in a single top-level html page with no included templates, you won't easily be able to separate concerns or decompose behaviors. Some other developer wouldn't be able to follow the work, and subtle bugs with unterminated tags may be harder to find. Plus: all that time fighting the framework could be spent working on getting your application to work.
As you suggest using ngRoute, you could just inject the $rootParams
-service into your controllers and get all the current params. If you also need the current controller selected by ngRoute, you should inject the $route
-service as well. See the example in the ngRoute documentation for more details on how to use these services - or provide a (minimal) version of your angular code to give you an example based on your use case.
BTW: If you also have different views and/or layouts (for example not only video) in your SPA, you could use ngRoute's ng-view directive to set up a viewport for all these different layouts. In that way each layout can have it's own template and a layout specific controller that can reuse generic controllers and directives (for example for comments). Again I need more code to give an meaningful example for that.
For what you want to do, I see three options.
$rootScope
to tie your controllers together; keep your URL variables here. When they change, your controllers can react accordingly. You could use $broadcast
and $emit
here for message passing, or you could just watch a $rootScope
variable.It sounds as though you want to avoid putting routing logic in each controller - which is good - but you'll have to find some way to specify the behavior you want. If I were going to try to roll this from scratch, I think I'd prefer the publish/subscribe route, myself; I prefer encapsulation in a provider for something like this (as it's modular and can be reused easily).
That said, I agree with the other answers here - it'd be far easier to simply use ngRoute
or uiRouter
. By doing this, you can set your routes in one place (along wtih route parameters) and either use nested controllers/views, or directives. You may consider converting your Video and Coments objects to Angular directives, actually.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With