Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preserve state with Angular UI-Router

I have an app with a ng-view that sends emails to contact selected from a contact list. When the users select "Recipient" it shows another view/page where he can search, filter, etc. "Send email" and "Contact list" are different html partials that are loaded in the ng-view.

I need to keep the send form state so when the users select someone from the Contact List it returns to the same point (and same state). I read about different solutions ($rootScope, hidden divs using ng-show, ...) but I want to know if UI-router will help me with it's State Manager. If not, are there other ready-to-use solutions?

Thanks!

like image 371
Jorgito Gutierrez Avatar asked Aug 02 '13 18:08

Jorgito Gutierrez


3 Answers

The solution i have gone with is using services as my data/model storage. they persist across controller changes.

example

the user service ( our model that persists across controller changes )

app.factory('userModel', [function () {
    return {
        model: {
            name: '',
            email: ''
        }
    };
}]);

using it in a controller

function userCtrl($scope, userModel) {
    $scope.user = userModel;
}

the other advantage of this is that you can reuse your model in other controllers just as easly.

like image 84
Anton Avatar answered Oct 02 '22 12:10

Anton


I'm not sure if this is recommended or not, but I created a StateService to save/load properties from my controllers' scopes. It looks like this:

(function(){
    'use strict';

    angular.module('app').service('StateService', function(){

        var _states = {};

        var _save = function(name, scope, fields){
            if(!_states[name])
                _states[name] = {};
            for(var i=0; i<fields.length; i++){
                _states[name][fields[i]] = scope[fields[i]];
            }
        }
        var _load = function(name, scope, fields){
            if(!_states[name])
                return scope;
            for(var i=0; i<fields.length; i++){
                if(typeof _states[name][fields[i]] !== 'undefined')
                    scope[fields[i]] = _states[name][fields[i]];
            }
            return scope;
        }

        // ===== Return exposed functions ===== //
        return({
            save: _save,
            load: _load
        });

    });
})();

To use it, I put some code at the end of my controller like this:

angular.module('app').controller('ExampleCtrl', ['$scope', 'StateService', function ($scope, StateService) {
    $scope.keyword = '';
    $scope.people = [];

    ...

    var saveStateFields = ['keyword','people'];
    $scope = StateService.load('ExampleCtrl', $scope, saveStateFields);
    $scope.$on('$destroy', function() {
        StateService.save('ExampleCtrl', $scope, saveStateFields);
    });
}]);
like image 40
JstnPwll Avatar answered Oct 02 '22 14:10

JstnPwll


I have found Angular-Multi-View to be a godsend for this scenario. It lets you preserve state in one view while other views are handling the route. It also lets multiple views handle the same route.

You can do this with UI-Router but you'll need to nest the views which IMHO can get ugly.

like image 26
Keith Avatar answered Oct 02 '22 13:10

Keith