简体   繁体   中英

Losing form input data when reinvoking a controller

I have a simple multi-view Angular application that implements a wizard, so each time a user clicks "Next" button, the app navigates to the next view, and same for "Back" button. I have a $routeProvider config that binds all views to the same controller. Each view represents a chunk of a huge form with input fields, and $routeProvider manages navigation across them:

app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
    $routeProvider.when('/salespoints', {
        templateUrl: 'salespoints',
        controller: 'main'
    })
    .when('/users', {
        templateUrl: 'users',
        controller: 'main'
    })
    .otherwise({
        templateUrl: 'partner',
        controller: 'main'
    });

    $locationProvider.hashPrefix('');
}]);

The problem is that each time a user clicks "Next" or "Back", the controller is invoked, so all the $scope changes that were made on previous steps are simply lost:

app.controller('main', ['$scope', function ($scope) {
    console.log('controller invoked'); // appears each time a user presses "Next" or "Back", hence re-instantiation of $scope
}]);

The application is small enough to turn to $rootScope in case every other method fails, but I just would like to avoid that as an anti-pattern.

What's the best way to keep $scope in latest state, with all changes made from the very beginning of app instance's lifecycle, and without re-instantiating it on every change of view?

Use a service to keep your form data and inject it into your controller.

angular.module('app').factory('formService', function () {
   var data = {};
   return {
      data: data
   };
});

angular.module('app').controller('ctrl', function(formService) {
   this.formData = formService.data;
});

Angular controllers are instanciated each time you have a new ng-controller in your template.

Angular services are instanciated only once , at the first time you need it, because they are singleton .

So angular services should be use to store data, especially data shared between multiple controllers instances (even if it's the same controller definition as in your example).

So, according to the advice of @joao-leal , I moved the data persistence to a new service and subscribed to $scope updates via $scope.$watch . The overall solution resulted into a quite simple code chunk:

app.factory('formPersistence', function () {
    var data = {};

    var get = function () {
        return data;
    };

    var set = function (updated) {
        data = updated;
    }

    var reset = function () {
        data = {};
    }

    return {
        get: get,
        set: set,
        reset: reset
    };
});

app.controller('main', ['$scope', 'formPersistence', function ($scope, formPersistence) {
    $scope.data = formPersistence.get();

    $scope.$watch('data', function () {                
        formPersistence.set($scope.data);
    });
}]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM