dotJEM / angular-routing

Enhanced state based routing for Angular applications!
https://dotjem.github.io/angular-routing/
MIT License
75 stars 9 forks source link

Rendering the application layout client-side #100

Closed vicentereig closed 9 years ago

vicentereig commented 10 years ago

Hi @jeme

I'm moving all the templates to the client-side. With https://github.com/pitr/angular-rails-templates it's straight forward to feed the $templateCache from templates under app/assets/javascripts/application/templates.

But I'm still rendering the application layout on the server-side. Meaning that the HTML containing the initialization directiveng-app and jem-view outlets are still rendered on the server. I'd like to keep it under app/assets/javascripts/application/templates/application.html and serve it packaged among all the JS assets and rest of the templates.

I'm at a point that I'm using angular.bootstrap to initialize and insert the app under the <body> tag. I guess that what I need to do next is to initialize the main outlet/view where the application.html will be rendered to and let angular render the main route normally.

I assume that the view initialization code is in here. Could you plase provide me some guidance? Would it be easier to use a parent route that renders application.html and the children would fill the outlets it defines? (is that actually possible? haven't succeeded yet).

Thanks, Vicente.

jeme commented 10 years ago

I must admit that I have not played around with manually bootstrapping angular, so I don't know what exactly happens during that process.

You mention both ng-app and angular.bootstrap, are you using those at the same time? They should not be used together according to:


To give a quick response that may give you a direction, ill try to explain a little about what kicks of the whole thing, as I can't give a qualified answer before I look deeper into it my self... If you can produce a Plunker or something that demonstrates the issue that would be great!

https://raw.github.com/wiki/dotJEM/angular-routing/images/angular-routing-services-interaction.png

Anyways, everything in angular-routing is actually kicked off by the built in location service, we rely on that when angular initializes it will also send of a location change event during initialization. That then triggers the routing service which handles matching routes and sending of the appropriate route change event, which is what finally triggers the state service.

The state service will then push updates to the view service which is the one holding the current view states.

From the other end of the perceptive, the actual view (or outlet) will request it's view state from the view service when being rendered the first time (compiled in angular terms)... end then begin to listen to events from the view service for changes happening after that point.

So what you could start by doing is examining if the pipeline is triggered correctly, starting with the $locationChangeSuccess event, after that event you can check various other events down though the pipeline:

var EVENTS = {
    LOCATION_CHANGE: '$locationChangeSuccess',

    ROUTE_UPDATE: '$routeUpdate',
    ROUTE_CHANGE_START: '$routeChangeStart',
    ROUTE_CHANGE_SUCCESS: '$routeChangeSuccess',
    ROUTE_CHANGE_ERROR: '$routeChangeError',

    STATE_UPDATE: '$stateUpdate',
    STATE_CHANGE_START: '$stateChangeStart',
    STATE_CHANGE_SUCCESS: '$stateChangeSuccess',
    STATE_CHANGE_ERROR: '$stateChangeError',

    VIEW_UPDATE: '$viewUpdate',
    VIEW_REFRESH: '$viewRefresh',
    VIEW_PREP: '$viewPrep'
};
jeme commented 10 years ago

Manual bootstrapping seems to work as expected: http://plnkr.co/edit/Iy6P764yiRYtX9i7JdIX?p=preview

So I am fairly sure I don't understand what your trying to do. Did any of the above pointers give you any direction? Any errors popped up or just no events at all?

vicentereig commented 10 years ago

Did any of the above pointers give you any direction? Any errors popped up or just no events at all

Indeed, that architecture review is extremely useful. Thanks a lot.

So I am fairly sure I don't understand what your trying to do.

I'm moving all the template rendering to the client-side. Including the main layout that normally gets rendered on the server side. Instead of rendering the following template on the server (HAML syntax used on purpose):

!!!
%head
  %title Regular Angular App — Layout template rendered on the server-side
%body
  .container(ng-app="app")
    .col-xs-3(jem-view="side")
    .col-xs-9(jem-view="main")
  %script(src="application.js")

I want to render the following server-side template (basically serving assets):

!!!
%head
  %title My Angular App/Framework— Layout template rendered on the client-side after angular bootstrap
%body
  %script(src="application.js")

Somewhere in my angular app I'll have a templates/application.html that will be served from the $templateCache in production mode:

  <div class="container">
    <div class="col-xs-3" jem-view="side"></div>
    <div class="col-xs-9" jem-view="main"></div>
  </div>

It will be rendered —by default— below the <body> tag after angular bootstrapping the app and it will host all the application views in the outlets it defines.

var bodyElement = document.querySelector("body");
angular.bootstrap(bodyElement, ['myApp']);

Therefore I believe I'll need to define a default root state (hard-coded somehow on app bootstrap) and populate a view in the view service that will actually let my application.html layout render under the <body>. Please note that I haven't had time yet to dive deeper in your architecture review.

https://raw.github.com/wiki/dotJEM/angular-routing/images/angular-routing-services-interaction.png

jeme commented 10 years ago

I am still not quite sure I fully grasp the whole concept, maybe because if I do, I don't quite understand why you use the manual bootstrap, it shouln't be any problem to deliver a "empty" html document that uses ng-app to bootstrap.

I am doing that my self in a ASP.NET environment where I use Razor to output a simple and empty html page...

Anyways, as for activating a default "state"... Currently we don't support any kinds of "default" syntax, this is because in the common case it's not really needed, and the "non-common" case it's easily done using 'run'...

What I expect to be the most common case is that we are hocked into routes, meaning that the default will most of the times simply be bound to the route: / ... But it's not as much a default state as it's just as state bound to /...

a) If by default we mean a state we go to when the URL matching fails, then $routeProvider.otherwise({ redirectTo: '/default/url' }) would be what we use, this can obviously also redirect to / etc.

b) In the case I don't expect to be so common is when you don't bind states to routes, here you can simply use:

app.run(['$state', function(state) {
  state.goto('about');
}])

http://plnkr.co/edit/w9h28ANhrP0nXjEKtBVk?p=preview (note that will work both with and without route bindings)

I don't know if that was something towards that you had in mind??

jeme commented 9 years ago

Closing due to inactivity.

(Feel free to request a reopen and provide more info)

vicentereig commented 9 years ago

Sure, no prob. Thanks @jeme.