RequireJs “map” configuration

map:

For the given module prefix, instead of loading the module with the given ID, substitute a different module ID.
This sort of capability is really important for larger projects which may have two sets of modules that need to use two different versions of ‘foo’, but they still need to cooperate with each other.
This is not possible with the context-backed multiversion support. In addition, the paths config is only for setting up root paths for module IDs, not for mapping one module ID to another one.
map example:

requirejs.config({
    map: {
        'some/newmodule': {
            'foo': 'foo1.2'
        },
        'some/oldmodule': {
            'foo': 'foo1.0'
        }
    }
});

If the modules are laid out on disk like this:
• foo1.0.js
• foo1.2.js
• some/
• newmodule.js
• oldmodule.js
When ‘some/newmodule’ does `require(‘foo’)` it will get the foo1.2.js file, and when ‘some/oldmodule’ does `require(‘foo’)` it will get the foo1.0.js file.
This feature only works well for scripts that are real AMD modules that call define() and register as anonymous modules. Also, only use absolute module IDs for map config. Relative IDs (like ‘../some/thing’) do not work.
There is also support for a “*” map value which means “for all modules loaded, use this map config”. If there is a more specific map config, that one will take precedence over the star config. Example:

requirejs.config({
    map: {
        '*': {
            'foo': 'foo1.2'
        },
        'some/oldmodule': {
            'foo': 'foo1.0'
        }
    }
});

Means that for any module except “some/oldmodule”, when “foo” is wanted, use “foo1.2” instead. For “some/oldmodule” only, use “foo1.0” when it asks for “foo”.
Note: when doing builds with map config, the map config needs to be fed to the optimizer, and the build output must still contain a requirejs config call that sets up the map config. The optimizer does not do ID renaming during the build, because some dependency references in a project could depend on runtime variable state. So the optimizer does not invalidate the need for a map config after the build.

For more info : http://requirejs.org/docs/api.html#config-map

Advertisements

Learning RequireJS

Why requirejs?

Why are we using requirejs? I’ve even asked it of myself. For me, organizing large javascript projects and managing dependencies led to it. There are lots of great posts about how to use requirejs but I wanted to focus on WHY.

Explicit Dependency Specifications :
Open up any significant sized javascript file with 100+ lines of code, even 50, and tell me, within 5 seconds, what dependencies it has. Can’t do it? You can with modules and requirejs.

function View() {
    this.name = ko.observable('bob');
    this.age = ko.observable(20);
    ...
}
var view = new View();
ko.applyBindings(view, $('viewPlaceHolder')[0]);    

versus

require(['jquery', 'knockout'], function($, ko) {
    // who knows whats in here, but I do know what it needs
});

How often do you use this information as a developer? Think about the value in not spending 5 minutes everytime you need to know, or more likely, the value in not creating a bug because you didn’t take the time to find them all or you missed one.

Explicit Export Specifications :

Along with explicit dependencies, modules have an explicit mechanism to define what they export. We can quickly read a module and know what it provides by looking at the return statement, instead of wondering what globals to access. define makes explicit that it is providing an interface to consumers.

define('math', ['dependencyA', 'dependencyB'], function(dependencyA, dependencyB) {
    // horrible things to local scope
    return {
            min: min,
            max: max,
            average: average
    };
});

Avoid Script Tag Soup :

<script src="scripts/utils.js">
<script src="scripts/numbers.js">
<script src="scripts/common.js">
<script src="scripts/formatting.js">
<script src="scripts/thing.js">
<script src="scripts/other.js">
<script src="scripts/site.js">

More info : http://devblog.wesmcclure.com/posts/why-requirejs

Using RequireJS :

Application Structure :

├── app.js
├── index.html
├── lib
│ ├── modules
│ │ └── template.js
│ ├── require.js
│ └── underscore.js

The data-main Attribute

Once you downloaded RequireJS, the first thing to do after you put its script in your solution is to understand how RequireJS starts working. Once RequireJS is loaded, it search for a script with data-main attribute (it should be the same script with the src attribute set to load RequireJS). The data-main should be set to the base Url for all the scripts. From the base Url, RequireJS will start loading all the relevant modules. Here is an example of a script tag with the data-main attribute:

<script data-main="app.js" src="lib/require.js"></script>

Configuring RequireJS

Another way to define the base Url is using the config function.

Now, let’s take a look at app.js.

require.config({
    //By default load any module IDs from scripts/app
    baseUrl: 'scripts/app',
    //except, if the module ID starts with "lib"
     paths: {
        lib: '../lib',
        jquery: "jquery-1.11.0.min"
    }, 
    // load backbone as a shim
    shim: {
        'backbone': {
            //The underscore script dependency should be loaded before loading backbone.js
            deps: ['underscore'],
            // use the global 'Backbone' as the module name.
            exports: 'Backbone'
        }
    }
});
  • The config Function :
  • If you want to change the default RequireJS configuration values with your own configurations, you can do that using the requirejs.config function. The config function receives an options object that can include a lot of configurations options. Here are some of the configurations that you can use:
    baseUrl – the root path to start the loading of modules.
    paths – path mapping for modules that don’t exists in under the baseUrl
    shim – configuration for dependencies, exports and initialization function to wrap scripts/modules that don’t use the RequireJS define function. For example, if underscore library doesn’t use the RequireJS define function and you still want to use it with RequireJS, you will have to define it as a shim in the config function.

    // Sets the configuration for your third party scripts that are not AMD compatible( that do not use define() to declare the dependencies and set a module value)

      shim: {
    
          "backbone": {
              deps: ["underscore", "jquery"],
              exports: "Backbone"  //attaches "Backbone" to the window object
          }
    
      } // end Shim Configuration
    

    The Shim configuration can also be used to make sure that that certain scripts executed in a particular order.
    http://requirejs.org/docs/api.html#config-shim
    deps – array of dependencies to load.

    Defining Modules Using RequireJS :
    Modules are just well-scoped objects that expose an API and encapsulate their internals. In order to define a module, RequireJS exposes the define function. There should be only one call for define in each JavaScript file by convention. The define function receives an array of dependencies and a function which is going to hold all the module definitions. By conventions the module definition function receives as parameters all the previous dependencies and in the order they were supplied in the array. For example, here is a simple module definition:

    define(["logger"], function(logger) {        
            return {
                 firstName: “John",
                 lastName: “Black“,
                 sayHello: function () {
                    logger.log(‘hello’);
                 }
            }
        }
    );
    

    Using The require Function :

    Another useful function in RequireJS is the require function. The require function is used to load dependencies without the creation of a module. For example, here is a usage of the require function which defines a function that require jQuery to work:

    require(['jquery'], function ($) {
        //jQuery was loaded and can be used now
    });
    

    Dynamically-loaded Dependencies :

    define(function ( require ) {
        var isReady = false, foobar;
     
        // note the inline require within our module definition
        require(["foo", "bar"], function ( foo, bar ) {
            isReady = true;
            foobar = foo() + bar();
        });
     
        // we can still return a module
        return {
            isReady: isReady,
            foobar: foobar
        };
    });
    

    you can use a synchronous require() as long as the module was already registered for that context:

    define(['require', 'lorem/ipsum'], function(require){
        // since 'lorem/ipsum' is on the dependency list it will be registered
        // before calling the definition function, so the synchronous require will
        // also work
    	var ipsum = require('lorem/ipsum')
        	console.log(ipsum.doSth());
    });
    

    But this would fail if the module dolor/amet wasn’t registered yet:

    define(['require'], function(require){
        	var ipsum = require('lorem/ipsum')
        	console.log(ipsum.doSth());
    });
    

    Some Tricks for Troubleshooting :

    You can use these API calls in your code if you need to, but I’ve actually found them quite useful when on the console in Chrome:
    require.defined(moduleId) – returns true if your moduleId has been defined and is ready for use.
    require.specified(moduleId) – returns true if your moduleId has been listed as a dependency by another defined module. Note that just because this returns true doesn’t mean your moduleId is ready to use (don’t you just love asynchrony?).
    Get module Url
    If you ever need to find the path to a given module, just use the following…

    var path = require.toUrl("./style.css");
    

    requirejs.s.contexts._.config – I learned about this from Vernon Kesner. This is technically a “back door/undocumented” call – so it could change or disappear without warning. However it returns a very useful object full of configuration info, see below:

    require

    This is the result of calling requirejs.s.contexts._.config inside a sample gif-generation app I used to demo Web Workers at Devlink. You can see all the relevant configuration data: the base URL, the paths we’ve mapped, the shim configuration, etc.
    Two other key items to know about when it comes to troubleshooting RequireJS are ‘errbacks’ and the requirejs.onError method.

    RequireJS “errbacks” :

    When you make a require call, you can include a third argument – a callback that receives an error argument, allowing you to react to the error, instead of ultimately generating an uncaught exception. The method signature, when using “errbacks” looks like this:

    require(
        [ "backbone" ], 
        function ( Backbone ) {
            return Backbone.View.extend({ /* your magic here */ });
        }, 
        function (err) {
            /* 
                err has err.requireType (timeout, nodefine, scripterror)
                and err.requireModules (an array of module Ids/paths)
    
                Inside here you could requirejs.undef('backbone') to clear
                the module from require locally - and you could even redefine
                it here or fetch it from a different location (though the
                fallback approach earlier takes care of this use-case more succinctly)
            */
        }
    );
    

    requirejs.onError :

    RequireJS has a global onError handler that will catch any errors not already handled by “errbacks”. To use it, simply set it like this:

    requirejs.onError = function (err) {
        /* 
            err has the same info as the errback callback:
            err.requireType & err.requireModules
        */
        console.log(err.requireType);
        // Be sure to rethrow if you don't want to
        // blindly swallow exceptions here!!!
    };
    

    http://backbonetutorials.com/organizing-backbone-using-modules/
    http://tech.pro/tutorial/1300/deep-dive-into-requirejs
    http://tech.pro/blog/1561/five-helpful-tips-when-using-requirejs

    JAX-WS Attachment – Enable MTOM

    It all begins with the fact that SOAP is XML. And when you send anything other than text, for instance, an image – it has to be converted into a datatype that an XML processor can understand.

    Without MTOM, your image will be converted to base64Binary and placed smack in the middle of your SOAP envelope. This conversion process makes the data fat.

    <tns:data>A very looooooooooooooooooooooong base64Binary string</tns:data>
    

    Here’s a simple illustration:

    lXWep

    With MTOM, the image will be transmitted outside the envelope as a MIME attachment – in short, it’s sent according to its original datatype: a jpg, png, or gif. Of course it’s still transmitted as binary data, but this time, there’s no XML-related conversion, avoiding the unnecessary overhead. XOP comes into the picture as it’s the one that gives the location of the externalized image.

    <soap:Body><soap:Envelope>
    
    <tns:data><xop:include href="SomeUniqueID-ThatLeadsToTheImage"/></tns:data>
    
    </soap:Body></soap:Envelope>
    
    Content-id: "SomeUniqueID"
    
    Content-Type: image/png
    
    image binary data here
    

    What is MTOM?
    MTOM (Message Transmission Optimization Mechanism) provides an efficient mechanism for transmitting binary data to and from web services over internet. MTOM uses XML binary Optimized Packaging or XOP to serialize and de-serialize binary part of an XML infoset.
    MTOM is a standard that is developed by the World Wide Web Consortium (W3C) and it is a SOAP Version 1.2 feature (based on the Infoset). Even though SwA (SOAP with Attachments) and MTOM are theoretically similar, and both encode binary data as a MIME attachment in a MIME document, SwA could be replaced by the more powerful MTOM and XOP mechanisms because it solves some of the interoperability issues of SwA. MTOM uses XOP in the context of SOAP and MIME over HTTP to achieve performance improvement.

    How Does XOP works?
    As we know, the serialization of XML infoset is text based and uses BASE64 binary-to-text encoding scheme, where the binary data represented in an ASCII string format. This increases the size of the XML payload.
    An MTOM-enabled web services engine detects the presence of Base64Binary data. XOP packaging process extracts the binary data out of the XML Infoset and the binary data serialized differently. XOP process extracts the binary part of the XML info-set and leaves the XML Infoset with the binary parts replaced by external references. This is called XOP infoset and the external reference is added as “xop:Include” element in XML. This makes MTOM actually a “by reference” method.
    The raw bytes are appended to the SOAP Message and are separated by a MIME boundary.
    The XOP package is created by serializing the XOP infoset and the binary data as a MIME attachment. Once the data is received at the other end, the XOP Package is de-serialized into the XOP Infoset plus the extracted content and the extracted content is placed back in the XML infoset where the corresponding external reference is present.
    See and example SOAP response below which uses MTOM. We will see the complete working example as we move on.

    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:retrieveImageResponse xmlns:ns2="http://globinch.com"> <return> <xop:Include href="cid:40128994-d019-4c2c-a293-49c448772ea7@example.jaxws.sun.com" xmlns:xop="http://www.w3.org/2004/08/xop/include"/> </return> </ns2:retrieveImageResponse> </S:Body> </S:Envelope>
    

    You can see the reference to the MIME attachment as

    <xop:Include href="cid:40128994-d019-4c2c-a293-49c448772ea7@example.jaxws.sun.com" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
    

    If you examine the SOAP header you will something like the below

    	
    Transfer-encoding  : chunked
    Content-type            : multipart/related;start="&lt;rootpart*75292b03-7617-4261-a44f-ac8d9df23382@example.jaxws.sun.com&gt;";type="application/xop+xml";boundary="uuid:75292b03-7617-4261-a44f-ac8d9df23382";start-info="text/xml"
    #status# : HTTP/1.1 200 OK
    

    The attachment details are as below

    Name: 40128994-d019-4c2c-a293-49c448772ea7@example.jaxws.sun.com	
    Content type: image/png	
    Size:431731	
    Part: 40128994-d019-4c2c-a293-49c448772ea7@example.jaxws.sun.com	
    Type: XOP	
    ContentId: 40128994-d019-4c2c-a293-49c448772ea7@example.jaxws.sun.com
    

    The contentId is same as the reference.

    Enabling MTOM in JAX-WS :
    In JAX-WS, it’s easy to enable MTOM for a web service endpoint by using either the @MTOM or @BindingType annotations. At the client side, MTOM can be enabled either by passing a new instance of MTOMFeature class when getting a reference to the web service endpoint (port), or by calling the SOAPBinding.setMTOMEnabled(true) method on the binding provider object. Here are the usages and examples in details.

  • Enabling MTOM for the web service endpoint
  • @MTOM annotation :

    The following example illustrates a web service endpoint is annotated with the @MTOM annotation:

    import javax.jws.WebMethod;
    import javax.jws.WebService;
    import javax.xml.ws.soap.MTOM;
    
    
    @WebService
    @MTOM
    public class MyWebService {
      
      @WebMethod
      public void upload(byte[] data) {
        // implementation details...	
      }
    }
    

    The @MTOM annotation has two optional parameters, enabled and threshold. The enabled parameter has a boolean value and indicates if MTOM is enabled for the JAX-WS endpoint. If an attachment is smaller than the size specified in threshold parameter, the runtime will inline the binary data as base64 binary instead of creating an attachment.

    @WebService
    @MTOM(threshold = 10240)
    public class MyWebService {
    }
    

    An alternative way is using the @BindingType annotation with an appropriate value for the SOAP version used. For example:

    Enabling MTOM with SOAP version 1.1:

    import javax.xml.ws.BindingType;
    import javax.xml.ws.soap.SOAPBinding;
    
    @WebService
    @BindingType(value = SOAPBinding.SOAP11HTTP_MTOM_BINDING)
    public class MyWebService {
    }
    

    Enabling MTOM with SOAP version 1.2:

    import javax.xml.ws.BindingType;
    import javax.xml.ws.soap.SOAPBinding;
    
    @WebService
    @BindingType(value = SOAPBinding.SOAP12HTTP_MTOM_BINDING)
    public class MyWebService {
    }
    

    From the above examples, we can see that using the @MTOM annotation is preferred as its succinct and flexibility (enabled/disabled and threshold).

    Enabling MTOM for the client :

    The following example shows how to enable MTOM at the client by passing a new instance of the MTOMFeature class when getting a proxy reference the web service endpoint:

    import javax.xml.ws.soap.MTOMFeature;
    
    MyWebServiceService service = new MyWebServiceService();
    MyWebService port = service.getMyWebServicePort(new MTOMFeature());
    

    Suppose that the MyWebServiceService and MyWebService classes are generated by the wsimport tool. And similar to the @MTOM annotation, we can also specify the enabled and threshold parameters in the MTOMFeature class’ constructor like this:

    boolean enabled = true;
    int threshold = 10240;
    MyWebService port = service.getMyWebServicePort(new MTOMFeature(enabled, threshold));
    

    And here’s an alternative way, calling the SOAPBinding.setMTOMEnabled(true) method:

    MyWebServiceService service = new MyWebServiceService();
    MyWebService port = service.getMyWebServicePort();
    
    BindingProvider provider = (BindingProvider) port;
    SOAPBinding soapBinding = (SOAPBinding) provider.getBinding();
    soapBinding.setMTOMEnabled(true);
    

    For more info :

    http://stackoverflow.com/questions/215741/how-does-mtom-work

    http://java.globinch.com/enterprise-java/web-services/jax-ws/jax-ws-attachment-enable-mtom-jax-ws-web-services/

    http://www.tuicool.com/articles/I3yEbu

    Be Stateless Be scalable

  • A stateful session bean can keep data between client calls. This means resources (memory, db connection, etc.) are held by the bean waiting for another call from the client.
  • By storing this state on the client and sending it with each request, you can have the same state, but with better scalability.
  • Stateless services make scaling out easier because it means that once a request has been processed, the next request from that web visitor does not necessarily have to come back to the same machine, which means you can (in theory) have as many machines as you want service the same kind of requests. If your traffic doubles in volume you just add the same number of machines and boom, you can now service twice as many requests.
  • SOAP Roles

    A node processing / forwarding a SOAP message is said to act in one or more SOAP roles. Here is a simple diagram showing 3 nodes (computers) involved in the processing of a SOAP message:

    soap-roles-1

    The first node is the sender. This role is not mentioned in the SOAP specification though.
    The second node is an intermediary node which forwards the SOAP message. Intermediary nodes may also alter the SOAP message. For instance, they may add, modify or remove header elements, or even change the body. Intermediary nodes are set to act in the next role.
    The last node in the diagram is the “ultimateReceiver” of the SOAP message. The ultimate receiver is the node that actually processes the SOAP message.

    Role :

    A SOAP message travels from the originator to the ultimate destination, potentially by passing through a set of SOAP intermediaries along the message path. A header can be targeted for a specific node or for the final node (i.e. SOAP 1.1 actor attribute or SOAP 1.2 role attribute), and when that happens the node must do something with the header. This can be either to use it or to ignore it.

    roles

    Note no role attribute present, so this header block is to be processed by the ultimate receiver of the message and no other node.

    A node processing / forwarding a SOAP message is said to act in one or more SOAP roles. Header blocks (elements) can be targeted at nodes acting in specific roles. In other words, if a header block is targeted for nodes acting in the “ultimateReceiver” role, then only nodes acting as ultimate receivers must process that header block. All other nodes should leave it unprocessed.
    Here is an example using the role attribute:

    <env:Header>
      <jj:maxTime value="10000" xmlns:jj="http://jenkov.com"
        role="http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver"
        />
    </env:Header>
    

    In this example the header element is only intended to be processed by the ultimate receiver of the SOAP message. Intermediary nodes should ignore this header element.
    When a SOAP Header child element contains a role attribute, only nodes acting in that role must process that element. All other nodes should leave it be.

    The mustUnderstand Attribute :

    The mustUnderstand attribute means that any node (computer) processing the SOAP message must understand the given header block. A “node” may not alway be the final receiver of the SOAP message. The message might be routed via intermediate nodes before ending up at the receiving / processing node (the final web service).
    In case an intermediate node does not understand the header block (element) containing the mustUnderstand attribute, it must return a SOAP fault.

    The mustUnderstand attribute indicates whether processing of the header is optional or mandatory. This basically translates to the node trying to find an appropriate handler that matches the header and proceed with processing the message in a manner consistent with its specification. If it can’t find an appropriate handler it must return an error and stop further processing. If mustUnderstand is true/1 the node is not allowed to ignore it.

    The mustUnderstand attribute should only appear on the root element of a SOAP header block. If it
    appears elsewhere, it should be ignored.
    The BP stipulates that the mustUnderstand attribute may only have the value “1” or “0”. The default
    value is “0”.

    Here is an example:

    <env:Header>
      <jj:maxTime value="10000" xmlns:jj="http://jenkov.com"
                   mustUnderstand="true"
        />
    </env:Header>
    

    It is not considered an error if the Ultimate Receiver receives a SOAP header block with the
    mustUnderstand attribute set to “1” and the role attribute specifying some role that the ultimate
    receiver does not take on.

    For more info :

    http://tutorials.jenkov.com/soap/roles.html

    http://tutorials.jenkov.com/soap/header.html

    OCWSD

    RESTful web service :

    @Path :

  • Paths are relative
  • Paths are relative. For an annotated class the base URI is the application path. For an annotated method the base URI is the effective URI of the containing class. For the purposes of absolutizing a path against the base URI , a leading ‘/’ in a path is ignored and base URIs are treated as if they ended in ‘/’. E.g.:

    @Path("widgets")
    public class WidgetsResource {
    
        @GET
        String getList() {...}
    
        @GET @Path("{id}")
        String getWidget(@PathParam("id") String id) {...}
    
    }
    

    In the above, if the application path is catalogue and the application is deployed at http://example.com/, then GET requests for http://example.com/catalogue/widgets will be handled by the getList() method while requests for http://example.com/catalogue/widgets/nnn (where nnn is some value) will be handled by the getWidget() method. The same would apply if the value of either @Path annotation started with ‘/’.

    A @Path value may or may not begin with a ‘/’, it makes no difference. Likewise, by default, a @Path value may or may not end in a ‘/’, it makes no difference, and thus request URLs that end or do not end in a ‘/’ will both be matched.

  • Regular expression in @Path
  • If it is required that a user name must only consist of lower and upper case alpha-numeric characters then it is possible to declare a particular regular expression, which overrides the default regular expression, “[^/]+?”, for example:

    @Path("users/{username: [a-zA-Z][a-zA-Z_0-9]*}")
    

    In this type of example the username variable will only match user names that begin with one upper or lower case letter and zero or more alpha numeric characters and the underscore character. If a user name does not match that a 404 (Not Found) response will occur.

    @Produces

    The @Produces annotation is used to specify the MIME media types of representations a resource can produce and send back to the client. In this example, the Java method will produce representations identified by the MIME media type “text/plain”.

    @Produces can be applied at both the class and method levels. Here’s an example:

    @Path("/myResource")
    @Produces("text/plain")
    public class SomeResource {
        @GET
        public String doGetAsPlainText() {
            ...
        }
    
        @GET
        @Produces("text/html")
        public String doGetAsHtml() {
            ...
        }
    }
    

    The doGetAsPlainText method defaults to the MIME type of the @Produces annotation at the class level. The doGetAsHtml method’s @Produces annotation overrides the class-level @Produces setting, and specifies that the method can produce HTML rather than plain text.

    If a resource class is capable of producing more that one MIME media type then the resource method chosen will correspond to the most acceptable media type as declared by the client. More specifically the Accept header of the HTTP request declared what is most acceptable. For example if the Accept header is:

    Accept: text/plain
    

    then the doGetAsPlainText method will be invoked.

    Alternatively if the Accept header is:

    Accept: text/plain; q=0.9, text/html
    

    which declares that the client can accept media types of “text/plain” and “text/html” but prefers the latter, then the doGetAsHtml method will be invoked.

    More than one media type may be declared in the same @Produces declaration, for example:

    @GET
    @Produces({"application/xml", "application/json"})
    public String doGetAsXmlOrJson() {
        ...
    }
    

    The doGetAsXmlOrJson method will get invoked if either of the media types “application/xml” and “application/json” are acceptable. If both are equally acceptable then the former will be chosen because it occurs first.

    The examples above refer explicitly to MIME media types for clarity. It is possible to refer to constant values, which may reduce typographical errors, see the constant field values of MediaType:

    APPLICATION_ATOM_XML          "application/atom+xml"
    APPLICATION_FORM_URLENCODED   "application/x-www-form-urlencoded"
    APPLICATION_JSON              "application/json"
    APPLICATION_OCTET_STREAM      "application/octet-stream"
    APPLICATION_SVG_XML           "application/svg+xml"
    APPLICATION_XHTML_XML         "application/xhtml+xml"
    APPLICATION_XML               "application/xml"
    MULTIPART_FORM_DATA           "multipart/form-data"
    TEXT_HTML                     "text/html"
    TEXT_PLAIN                    "text/plain"
    TEXT_XML                      "text/xml"
    WILDCARD                      "*/*"
    

    AngularJs UI-Router

    ui-router :
    uiRouter is an alternative router for AngularJS v1.0. Instead of configuring a list of routes, you configure states.
    Changing State
    There are three ways to change the state and thus change the UI

    click a link with a ui-sref attribute
    <a ui-sref="state-name">link text</a>
    call

    $state.go('state-name');

    must inject $state to use

    navigate to the URL of a state

    typically by calling

    $location.path(url)

    or typing it into the browser address bar

    state :

    To define a route, we use the .config method and set our states on the $stateProvider.

    var starter = angular.module('starter', ['ionic', 'controllerModule'])
    .config(function($stateProvider, $urlRouterProvider) {
      $stateProvider
        .state('addOrder', {
          url: '/AddNewOrder',
          template: "<h1>HELLO!</h1>"
        }
        });
    });
    
    <body ng-app="starter">
        <div id='content' ng-controller='mainController'> 
             <a ui-sref="addOrder"> Add New Order </a></li>
             <div ui-view="main"></div>      
      </div>
    </body>
    

    template, templateUrl, templateProvider :

    We can set up templates on each of our views using one of the three following options:

    template – A string of HTML content or a function that returns HTML
    templateUrl – A string URL path to a template or a function that returns a URL path string
    templateProvider – A function that returns an HTML content string

    $stateProvider.state('home', {
      template: '<h1>Hello {{ name }}</h1>'
    });
    

    URL :

    The url option will assign a URL that the application is at to a specific state inside our app.

    $stateProvider
      .state('inbox', {
        url: '/inbox',
        template: "<h1>Welcome to your inbox</h1>"
      });
    

    When the user navigates to /inbox, then the app will transition into the inbox state and fill the main ui-view directive with the contents of the template “Welcome to your inbox”.

    Views :

    We can set multiple named views inside of a state. This feature is a particularly powerful one in ui-router: Inside of a single view, we can define multiple views that we can reference inside of a single template.

    If we set the views parameter, then the state’s templateUrl, template, and templateProvider will be ignored. If we want to include a parent template in our routes, we’ll need to create an abstract template the contains a template.
    Let’s say we have a view that looks like:

    <div>
      <div ui-view="filters"></div>
      <div ui-view="mailbox"></div>
      <div ui-view="priority"></div>
    </div>
    

    We can now create named views that fill each of these individual templates. Each of the subviews can contain their own templates, controllers, and resolve data.

    $stateProvider
      .state('inbox', {
        views: {
          'filters': {
            template: '<h4>Filter inbox</h4>',
            controller: function($scope) {}
          },
          'mailbox': {
            templateUrl: 'partials/mailbox.html'
          },
          'priority': {
            template: '<h4>Priority inbox</h4>',
            resolve: {
              facebook: function() {
                return FB.messages();
              }
            }
          }
        }
      });
    

    Controller :

    Just like in ngRoute, we can either associate an already registered controller with a URL (via a string) or we can create a controller function that operates as the controller for the state.

    If there is no template defined (in one of the previous options), then the controller will not be created.

    Steps to use the ui-router :

    Download :

    download from https://github.com/angular-ui/ui-router
    just need one file from release folder… angular-ui-router.min.js

    Include :

    <script src="js/angular-ui-router.min.js"></script>
    

    Add module dependency :

    Add ui-router as a module dependency

    var app = angular.module('app-name', ['ui.router']);
    

    How to use :

  • use ui-view directive
  • When dealing with routes and states inside of ui-router, we’re mainly concerned with which state the application is in as well as at which route the web app currently stands.
    The templates we define at any given state will be placed inside of the

    <div ui-view></div>

    element of the route or state it was called. Each of these templates can include their own ui-view as well, which is how we can have nested views inside our routes.

    Wherever a view is desired use

    <div ui-view>initial content</div>

    When dealing with routes and states inside of ui-router, we’re mainly concerned with which state the application is in as well as at which route the web app currently stands.the templates we define at any given state will be placed inside of the

    <div ui-view></div>

    element.

    The ui-view directive tells $state where to place your templates. A view can be unnamed or named.

    <!-- Unnamed -->
    <div ui-view></div> 
    
    <!-- Named -->
    <div ui-view="viewName"></div>
    

    You can only have one unnamed view within any template (or root html). If you are only using a single view and it is unnamed then you can populate it like so:

    <div ui-view></div>
    
    $stateProvider.state("home", {
        template: "<h1>HELLO!</h1>"
    })
    

    The above is equivalent to specifying your view explicity, by name, in this case an empty name:

    $stateProvider.state("home", {
        views: {
            "": {
                template: "<h1>HELLO!</h1>"
            }
        }    
    })
    

    But typically you’ll only use the views property if you name your view or have more than one view in the same template. There’s not really a compelling reason to name a view if its the only one, but you could if you wanted, like so:

    <div ui-view="main"></div>
    
    $stateProvider.state("home", {
        views: {
            "main": {
                template: "<h1>HELLO!</h1>"
            }
        }    
    })
    

    Really though, you’ll use views to set up multiple views:

    <div ui-view></div>
    <div ui-view="chart"></div> 
    <div ui-view="data"></div> 
    
    $stateProvider.state("home", {
        views: {
            "": {
                template: "<h1>HELLO!</h1>"
            },
            "chart": {
                template: "<chart_thing/>"
            },
            "data": {
                template: "<data_thing/>"
            }
        }    
    })
    
  • use ui-sref directive
  • A directive that binds a link (“anchor(a)”) to a state. If the state has an associated URL, the directive will automatically generate & update the href attribute via the $state.href() method. Clicking the link will trigger a state transition with optional parameters. Also middle-clicking, right-clicking, and ctrl-clicking on the link will be handled natively by the browser.

    Usage:

    ui-sref=’stateName’ – Navigate to state, no params. ‘stateName’ can be any valid absolute or relative state, following the same syntax rules as $state.go()
    ui-sref=’stateName({param: value, param: value})’ – Navigate to state, with params.

    <!-- index.html -->
    <body>
        <div ui-view></div>
        <!-- We'll also add some navigation: -->
        <a ui-sref="state1">State 1</a>
    </body>
    

    Working Example :

    index.html
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
        <title></title>
        <link href="css/style.css" rel="stylesheet">
        <script src="lib/angular.min.js"></script>
        <script src="lib/angular-ui-router.js"></script>
        <!-- your app's js -->
        <script src="js/app.js"></script>
        <script src="js/controllers.js"></script>
      </head>
      <body ng-app="starter">
        <div id='content' ng-controller='mainController'>
                    <a ui-sref="addOrder"> Add New Order </a>
                    <div ui-view="addOrderView"></div> 
                    <button ng-click='showOrders()'>Show Orders</button>               
                    <div ui-view="showOrdersView"></div>                  
        </div>
      </body>
    </html>
    
    app.js
    var starter = angular.module('starter', ['ui.router','controllerModule'])
    .config(function($stateProvider, $urlRouterProvider) {
      $stateProvider
        .state('addOrder', {
          url: '/AddOrder',
          views: {
          'addOrderView': {
            template: '<h4>Add Order</h4>'
          }
        }
        })
         .state('showOrders', {
          url: '/ShowOrders',
          views: {
          'showOrdersView': {
            template: '<h4>Show Orders</h4>'
          }
        }
        });
    });
    
    controllers.js
    angular.module('controllerModule', [])
    
    .controller('mainController', function($rootScope, $state, $stateParams) {
    	$rootScope.showOrders = function(){
    		$state.go('showOrders');
    	 }
    });
    

    For more info :

    https://github.com/angular-ui/ui-router/wiki/Quick-Reference#stateproviderstatestatename-stateconfig

    http://www.ng-newsletter.com/posts/angular-ui-router.html

    http://java.ociweb.com/mark/other-presentations/AngularJS-ui-router.pdf

    http://cnpmjs.org/package/angular-ui-router

    https://github.com/angular-ui/ui-router/wiki/Quick-Reference#note-about-using-state-within-a-template