ui-router inside custom angular directive, make sense? - angularjs

I'm working on an isolated scope custom directive that has a few different states.
Does it make sense to use ui-router/ui-view inside this directive in order to handle the states?
It's a "note widget" that lists notes. If there are no notes, it displays a message instead of the list that says they should add a note. If notes are being loaded, it shows that notes are being loaded. If a user adds a note by clicking the add I mentioned above or the + then the view is a textbox. So there is at least 4 different views.
My initial instinct is that it would be polluting the directive and giving it a hard dependency to ui-router and my application because it defines the states. Am I just over worried?

I would tell it this way: yes, use the ui-router, but not for a directive - use it for your appliation. In fact, the best you can do is to read few blog posts and go through sample application to understand the principles. You'll soon realize, that there is no need to use the ui-router partially..
from The basics of using ui-router with AngularJS (by Joel Hooks)
...ui-router fully embraces the state-machine nature of a routing system. It allows you to define states, and transition your application to those states. The real win is that it allows you to decouple nested states, and do some very complicated layouts in an elegant way.
You need to think about your routing a bit differently, but once you get your head around the state-based approach, I think you will like it...
and here AngularJS State Management with ui-router (by Ben Schwartz)
...The most interesting thing about AngularJS's new router, isn't the router itself, but the state manager that comes with it. Instead of targeting a controller/view to render for a given url, you target a state. States are managed in a heirarchy providing inheritance of parent states and complex composition of page components, all the while remaining declarative in nature...
Here I put together all the links, up to date, targeting the sample example, the most interesting code snippet sample.js..
Summary, try to implement the ui-router on the application level. Directive could then by a conductor only, helping your users to navigate, to walk through among states...

Related

Why UI router if I can use directives?

Well, I have never used and never felt like that I should use the UI router. I was asked in one of the interviews about this and so felt like reading if I am missing something out as an AngularJs developer.
Now, the explanations on internet displays it's strength based on the modularity and reusability of the components. Nesting of views etc.
If I want to reuse components in my view, then can't I use directive instead of a new state? According to this article by scotch.io(top google result) for ui router we can use separate data /controllers in my view. Well, can't I do the same via directive's controller and template. I can still reuse as many times as I want it.
Please let me know if I am missing some cool feature and makes it quintessential to use it in an AngularJs application (yeah a larger one with lots of reusable components of course) .
The whole point of the router is that it uses the URL to change states. If you just used directives, you would have to write your own mechanism for syncing up URLs with specific directives.
AngularJS is a framework for Single Page Application.
Single Page Application (SPA)
Single Page Application is a web application that loads single HTML page and dynamically updates a fragment in the page as the user interacts with the app.
John Papa's blog explains SPA in simple terms.
The biggest advantage of SPA that I see is
once the application is loaded, the state is maintained without
requiring server roundtrip when user navigates.
Users can bookmark deep link into your application. SPA framework (AngularJS) will take care of loading the required state when user open bookmark.
Although it is technically possible to achieve the above in a non-SPA application, it was never as simple as SPA.
SPA is useful for highly complex applications with many pages. For simple applications with 2-3 pages jQuery is the way to go.
Read Single Page Application: advantages and disadvantages for more discussions
You probably know all these and I think you are trying to achieve SPA using directive.
Routing
Routing framework loads a view dynamically based on user action into the main page without refreshing the whole application; providing SPA effect.
There are two popular AngularJS routing frameworks available.
ngRoute
UI-Router
ngRoute is based on URL mapping and UI-Router is based on state name mapping. I prefer UI-Router.
Routing vs Directive
Now, the explanations on internet displays it's strength based on the
modularity and reusability of the components. Nesting of views etc.
Yes directive is used for modularity and reusability and can load views dynamically but cannot choose a view dynamically based on user action. You have to write complex conditions within directive to choose a view dynamically.
For example, if you have an application with 3 links and you need to show a view based on the link user clicked.
Using directive you need to keep track of what the user clicked and write a mucky condition to choose a view to display. Most of the time you will fail to achieve the effect because the link can be accessed in multiple ways.
On the other hand, once routing is configured, the corresponding template will be dynamically loaded when user clicks the link. It is way easier to change the view based on user action.
Another advantage. When user opens a bookmark deep linked into the application, routing framework will take care of loading the sate (It is impossible to achieve this using directive). It feels more natural way of designing an application.
Choice is yours.

What is an Angular State?

I am from Asp.Net world, trying to understand what an Angular State mean.
What is an Angular State? Is it similar to an ascx component in Asp.Net? Is it a sub page? Is it similar to a workflow state?
I heard many people talking about it, and I have been trying to search for articles which explains what a state is or does, but cannot find a good one for the beginner.
Do any of you know any good article? could you please help me to grab/understand the concept of angular state? thanks a lot. :-)
The reference is not to Angular itself but to an Angular Module called Angular UI.Router. This module allows you to turn your Angular application into a State Machine, and handle what appears on the view based on these states, rather than only on the URL parameters. Many people consider this an essential Angular Module, and far more functional than the default $routeProvider.
The best reference for all the $stateProvider
features is the github repository wiki.
From the documentation for the AngularJS UI-Router,
A state corresponds to a "place" in the application in terms of the overall UI and navigation.
A state describes (via the controller / template / view properties) what the UI looks like and does at that place.
States often have things in common, and the primary way of factoring out these commonalities in this model is via the state hierarchy, i.e.
parent/child states aka nested states.

General approach of left side menu that loads different content in a center of the page

I've started to learn AngularJS but I need some application design hints. Of course I'm not asking about the layout but ... how to design my application and it's controllers in a proper way. I have left sidebar with a menu that is loaded from the web using JSON. That needs a controller. That's fine. It works for me. There's a content box as well in a center of my page that loads some data dynamically. In my opinion it requires another controller.
And now comes my solution, that somehow doesn't look good IMHO. When I click a menu item in my sidebar I'm loading a content. Then I'm passing this data into a Service which emits an Event afterwards to the Second controller (which is responsible for controlling my content in a center of my page). When it receives this event it simply gets previously loaded data from the Service and displays it. It generally works.... but ... I'm pretty sure that's not the proper way of doing this.
I would be grateful for any hints. AngularJS has a really poor documentation and tutorial :(
cheers
EDIT:
OK. That's my basic application using JQuery:
http://greatanubis-motoscore.rhcloud.com/index
And that's the same application I'm converting into AngularJS:
http://greatanubis-motoscore.rhcloud.com/angular/index
No worries, some text is in Polish but... I think it really doesn't matter ;)
Note for the AngularJS version: At the moment the content is a HTML but finally it will load JSON data as the other controllers.
I would go about doing this with angular ui-router. With ui-router you can achieve this in a couple of ways. You can use nested routing to have a base state (Your sidebar menu, header etc.) which will act as your shell page, this can have its own controller as well. You could then define each of those other views as child states of the base state. These child states can also have their own controller/views as well, but they will be sitting inside the base state (both visually, and also inherit $scope properties of the base state) optionally they can have separated URLs themselves, but they don't have to, you can just change states without changing the url, by leaving the URL bit empty when you define different states in your $stateProvider configs. Another way would be to use the multiple named views feature.

angular ui-router best practice inheritance vs metadata

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.

Changing my backbone.js router

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.

Resources