How to automatically enter a state parameter

annotation

Hi I am using angular + ui-router in my project, I have a huge number of nested states and different views, which in turn contain a huge number of different inputs, the user fills in these inputs gradually step by step.

Problem

Sometimes users need additional information located in the previous step, and the "Back" button of browsers helps the user to look into this data, but as soon as the user clicks on it, the information that he has already entered is lost due to the state transition, which is obviously badly.

Strategy

To overcome the described problem, I have the following plan:

  • Associate each custom "navigation" (assuming this is the correct term) with a random id
  • To prevent problems of inheritance inheritance and serialization, instead of putting the viewmodel in $scope

    use a regular javascript object that will store the immediate values ​​bound to the UI.
  • Add an observer to search for changes in this "repository"
  • Once the change is noticed, serialize the object and save it

Clarifications

Why do we need a random parameter in the URL?

We don't want to store all of the data in the url as there can be quite a lot of data that won't fit in the url. Therefore, to provide guarantees, the URL will not break, we only put a small random GUID / UUID in it, which later allows us to retrieve the data associated with the current "navigation" using this random GUID / UUID.

Vault

There is plenty of available storage scenarios: LocalStorage

, IndexedDB

, WebSQL

, Session Storage

, you name it, but because of their cross-tabs, cross-browser-specific nature of the browser would be difficult to manipulate and manage all data that fall within the store. The implementation will be buggy / server side support may be required.

Thus, the most elegant storage strategy for this scenario would be to store the data in a special variable window.name

that is capable of storing data between requests. This way, the data is safe until you close the tab.

Question

On behalf of everything written above, I have a root view called "view" that has a state parameter id

(this is a random GUID / UUID)

$stateProvider.state('view', {
    url: '/view/{id}',
    controller: 'view',
    templateUrl: 'views/view.html'
});

      

All other views follow from this view, is there a way to make a directive ui-sref

to automatically inject a random GUID / UUID into the state parameter of id

my root view instead of writing each time ui-sref

like

<a ui-sref="view({id:guid()}).someNestedView({someNestedParam: getParam()})"

      

I would like to have something like:

<a ui-sref="view.someNestedView({someNestedParam: getParam()})"

      

+2


source to share


1 answer


AOP and Decorator image is the answer. A full description can be found here:

Experiment: Designing Directives from Jesus Rodriguez

A similar solution, as described below, could be observed:

Changing default behavior of $ state.go () in ui.router to reload by default

How does it work? There is a link to a working example



In this case, we don't decide which source the random GUID comes from. Let's keep it simple at runtime:

var guidFromSomeSource = '70F81249-2487-47B8-9ADF-603F796FF999';

      

We can now introduce a decorator like this:

angular
.module('MyApp')
.config(function ($provide) {
    $provide.decorator('$state', function ($delegate) {

        // let locally use 'state' name
        var state = $delegate;

        // let extend this object with new function 
        // 'baseGo', which in fact, will keep the reference
        // to the original 'go' function
        state.baseGo = state.go;

        // here comes our new 'go' decoration
        var go = function (to, params, options) {
            params = params || {};

            // only in case of missing 'id'
            // append our random/constant 'GUID'
            if (angular.isUndefined(params.id)) {

                params.id  = guidFromSomeSource;
            }

            // return processing to the 'baseGo' - original
            this.baseGo(to, params, options);
        };

        // assign new 'go', right now decorating the old 'go'
        state.go = go;

        return $delegate;
    });        
})

      

The code should be self-explanatory, check it out in action here

+2


source







All Articles