As we plan to use Chaplin for Mobile and want to keep it lightweight, is it possible we use Chaplin without routes, but activate the controller manually (we will use a single controller only, but possibly multiple views) ?
Can this be done by just using the dispatcher?
Controllers expect routes as parameters in a number of their methods. Similarly, the dispatcher is tightly coupled with routes management, and it does all the controller loading, callbacks and execution.
If you want to do away with routes, you'll have to rewrite the dispatcher to get rid of routes, and modify the new method of the controllers to disregard routes.
Alternatively, set up only a single route and it'll do exactly what you want. Why do you want to get rid of routes? One route, one controller. The dispatcher works fine in that case, and has very little overhead because the controller behavior is cached when the route doesn't change.
Related
I am building small app using angularjs and nodejs and i would like to know what is best use case for $stateprovider and $routeProvider.
Please help
Angular's own ng-Router takes URLs into consideration while routing, UI-Router takes states in addition to URLs.
States are bound to named, nested and parallel views, allowing you to powerfully manage your application's interface.
While in ng-router, you have to be very careful about URLs when providing links via tag, in UI-Router you have to only keep state in mind. You provide links like . Note that even if you use in UI-Router, just like you would do in ng-router, it will still work.
So, even if you decide to change your URL some day, your state will remain same and you need to change URL only at .config.
While ngRouter can be used to make simple apps, UI-Router makes development much easier for complex apps.
$stateprovider is used when you want the app to have different states like if you want jst a small section of a screen to be loaded at times instead of the entire screen, the go for State provider and the $state.go(url). Special cases when you have a Sliding Drawer sort of an implementation, where you have a right menu with buttons which load different sub screens.
$routeProider are commonly used. Mostly when you want the entire screen to be changed and redirected to a new one.
Note
While using the $state.go(url); for redirecting your screen, the real link of your screen won't change. It will just change the state and not the url of the page
Not to confuse the issue, but there is a new option in AngularJS 1.5: ComponentRouter
This router, along with the uiRouter ($stateProvider) give you more flexibility than the legacy ngRouter ($routeProvider). The ComponentRouter and uiRouter both have a future if you migrate to Angular2.
That said, it depends on your needs. You may not need the composable and nested views offered by ComponentRouter and uiRouter -- but instead only need simple routes.
I'm structuring a Multi Page App in angular. I have a main app with its ngRoute configured so that the resulting url is something like:
http://localhost:8080/project/main#firstTemplate
http://localhost:8080/project/main#secondTemplate
http://localhost:8080/project/main#thirdTemplate
...
Now I must move to another app in the same project so that the Url is something like:
http://localhost:8080/project/secondary#fourthTemplate
I'm able to achieve this by manipulating the string resulting by $location.absUrl() and pass it to $window.location.href but it's horrible.
Is there a better way to do the same thing?
You should do this by the means of your router. There is a default router in angular, though I would suggest you going with https://github.com/angular-ui/ui-router - as I think it is much better than Angular v1.x defaults.
With that router you can define few states (1 state per each URL), define URL for each state, define views to be displayed in that state, actions on entry/leave etc. Then, you can get access to $state object and its go() method to switch between states - as well as easily have it done automatically on elements by specifying .
I am converting my application from ngRoute to uiRouter. I have read and watched a lot of tutorials but I am still lacking the experience to decide on best practices.
First of all a major change I have done is break the state declaration to each module/controller. This feels more natural and cleaner to me but introduces some complexity when wanting to apply a global rule to many states. For example half my routes require authentication and the other half do not.
With ngRoute I had a data attribute denoting the auth level required in each route. With uiRouter I understand there is this way of doing it and there is the state inheritance way. So a route could be public.myRoute where public is an abstract route declared at the application level. This creates the issue though of the module not being able to work standalone if someone does not define the public state.
In contrast if I add a metadata attribute in the data object, like "auth_level: user" this would not affect the module if no one is dealing with it. But this feels more "magic" and less maintainable.
The same issue arises with the navigation bar. Half my views have a navigation bar and the other half don't. Until now I used a isNavbarVisible boolean attribute but I understand this should be part of the state? Maybe a second ui-view in the layout.html template instead of using ng-include with ng-if as I did so far?
Finally, I am wondering about the best practice in requiring a promise in every route to be resolved. For example, no matter where the application entry point is, the user rights should be resolved first before loading the view. In ngRoute I was looping through all the routes in their definition and adding that promise.
Is there a good guide for best practices when migrating from ngRoute to uiRouter, because other than generic recommendation like "replace ng-include" with a name ui-view or that state inheritance should be preferred, I haven't found any concrete implementations demonstrating that.
I am in the same situation than the question author, Here's some very interesting information about how to drive this change.
https://github.com/angular-ui/AngularJS-StyleGuide
ui-router is a 3rd-party module and is very powerful. It supports everything the normal ngRoute can do as well as many extra functions.
Here are some common reason ui-router is chosen over ngRoute
ui-router allows for nested views and multiple named views. This is very useful with larger app where you may have pages that inherit from other sections.
ui-router allows for you to have strong-type linking between states based on state names. Change the url in one place will update every link to that state when you build your links with ui-sref. Very useful for larger projects where URLs might change.
There is also the concept of the decorator which could be used to allow your routes to be dynamically created based on the URL that is trying to be accessed. This could mean that you will not need to specify all of your routes before hand.
states allow you to map and access different information about different states and you can easily pass information between states via $stateParams.
You can easily determine if you are in a state or parent of a state to adjust UI element (highlighting the navigation of the current state) within your templates via global $state provided by ui-router
Overall, ngRoute merely allows you to assign controllers and templates to URL routes, whereas the fundamental abstraction in ui.router is states, which is a more powerful concept.
I have a web application with require.js, backbone.js and jquery.
The brief structure of the app is as follows:
There are 2 sections on the screen (toolbar and main content below).
There are multiple components (address management, event management), each triggered by a hash fragment change and require a
page transition.
There is one backbone.js router. It's the heart of the application. The router is activated with a new hash fragment (manually entered,
back button, menu item selection).
Up until now, in the router, I made the page transition, I DIRECTLY called the controller ("view" in backbone) of the selected component.
So there's a CENTRAL handling of controller calling.
But this has to change now to a DISTRIBUTED handling. I now need to respond to a new hash fragment from two different places: From the toolbar component and from router.
So my idea is to exchange the direct controller calling mechanism with pub sub. Now MULTIPLE components could register for a special action and the router just "fires the event".
I searched around and found Chaplin (https://github.com/moviepilot/chaplin), a backbone.js example application.
The developers of Chaplin seem to have a similiar thing called "ApplicationView" (https://github.com/moviepilot/chaplin#toc-router-and-route):
"Between the router and the controllers, there’s the ApplicationView as
a dispatcher."
Is there anyone who has already this kind of architecture and can tell me his experience with this or has anybody solved this in another way?
I've used a similar, though maybe less complex, architecture in this project. I give a pretty good explanation in this answer to a related question. The quick overview:
I manage app-wide events that change the application state using a singleton State model that works similarly to Chaplin's pub/sub architecture. This is just a basic Backbone model, with some added methods to deal with serializing and deserializing attributes as strings, so they can be set in the URL.
Application components that change the application state in response to user interaction or other input do so by setting properties on app.state.
Components that need to update when the application state changes do so by binding to change events on app.state (it looks like this is exactly the way Chaplin's mediator works, though they renamed the methods to fit the pub/sub paradigm).
I treat my routers like specialized views that update the address bar and respond to user input in that area. Changing the address (manually or by clicking on a link) causes the router to set() the necessary changes on the app.state model, and everything else updates accordingly.
I hope that's helpful - I think it's a little simpler than the Chaplin approach.
Update: i wrote some wrong statements about the use of header in php; so forget that part :)
What i want is to fetch and display a controller's view (with controller's data) from another controller, without have url change in browser.
Some details:
Redirect doesn't do the job because is a direct redirect (via browser)
requestAction doesn't allow me to fetch css and images correctly
I need this thing because i have a controller dispatcher that redirects internally to the other controllers.
I think the only (correct) solution is to use routes.php in /config with Router::connect
and there use the logic that was in the dispatcher controller.
ummm... header() is the function to use for a redirect unless the PHP documentation is wrong. (http://php.net/manual/en/function.header.php) The core in cakePHP uses header for the redirect function (see lines 721 - 730 of cake/libs/controller.php).
So I am not certain what you mean "like normal PHP". CakePHP is PHP, it's just built on object oriented code. It's not magic or twisted ways of doing things. So to do a redirect in cake, you can simply use:
$this->redirect(array('controller' => 'my_controller', 'action' => 'my_action'));
And it will call the header() function.
Now. If you are dead set on not using redirect (maybe if you are going to an external site), you can call header() in the code. Just be sure you put the exit(); after the header call:
header('Location: http://call/my/url');
exit();
It will work just the same as redirect. It's just a lot of unnecessary extra work. Keep in mind that using redirect will maintain the domain name and build the URL for you automatically.
In general, connecting URLs to controllers is the job of routes. If your logic is rather complex and normal routes won't cut it, you can even write your own route parser class that does more complex logic (that's all in the manual).
If this routing logic involves database queries or any other sort of controller logic and may lead to very different output for the same URL based on some internal state though, you're making a very RESTless application and I'd submit you should rethink what you're trying to do. Having said that, you can render any view from any controller action using $this->render(). The controller logic for each view could be put in the AppController or possibly (partly) the models to be called from anywhere. So instead of "redirecting" to a different controller, a route just routes to a specific controller action as usual, that action dynamically calls code it needs to call and then renders the view it needs to render.
If you want your app to stay on the same URL but display very different content, you should probably also look into making an AJAX app.
The right solution for you is probably somewhere in between.