Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

not allow to navigate if any changes on form using $dirty and $pristine

I'm trying to stop navigation on my application if any form made changes and try to navigate without saving changes.

i want to show a dialog to show whether to save navigate or discard or cancel navigation action.

i'm using angular ui.routing

app.config(function($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise('/dashboard');

    $stateProvider
        .state('dashboard', {
            url: '/dashboard',
            templateUrl: '/application/private/views/dashboard.html'
        })
        .state('websites', {
            url: '/websites',
            templateUrl: '/application/private/views/websites.html'
        })
});

i was planning to have implementation something like using angularjs service singleton

app.service('dirtyCheckService', function ($rootScope, dialogService){


});

and on controller level i can write a submit click like this

app.controller('formSubmitCtrl', function ($scope, dirtyCheckService){
dirtyCheckService.checkForm($scope).then(function(){
   //allow navigation
   },function(){
   //not allowed}
});

i'm not sure is there easy way exist already or not

thanks you

like image 449
Gayan Avatar asked Aug 23 '14 06:08

Gayan


2 Answers

The answer is: It is ok to move that kind of check into service/factory - for some further reuse. Also, here is some example at least to show how to - plunker

A factory:

.factory('CheckStateChangeService', function($rootScope){

  var addCheck = function($scope){ 

    var removeListener = $rootScope.$on('$stateChangeStart'
        , function (event, toState, toParams, fromState, fromParams) {

          if($scope.form.$pristine)
          {
            return;
          }

          var shouldContinue = confirm("The form has changed" +
                 ", do you want to continue without saving");
          if(shouldContinue)
          {
            return;
          }
          event.preventDefault();
    }); 

    $scope.$on("$destroy", removeListener);
  };

  return { checkFormOnStateChange : addCheck };
})

And having a view like this:

<div>
    <form name="form">

      <dl>
        <dt>Name</dt>
        <dd><input type="text" ng-model="person.Name" />
        <dt>Age</dt>
        <dd><input type="number" ng-model="person.Age" />
      </dl>

    </form>
</div>

And the controller:

.controller('MyCtrl', function($scope, CheckStateChangeService) {

  $scope.person = { Name: "name", Age: 18 };

  CheckStateChangeService.checkFormOnStateChange($scope);

})

There is an example

like image 82
Radim Köhler Avatar answered Sep 28 '22 14:09

Radim Köhler


You're right about a service being the way to do this, something like this should do:

$scope.$watch("myForm.$dirty",function(v){
     dirtyCheckService.setDirty(v);
},true)

Then maybe somewhere in your app, such as the run block:

app.run(function($rootScope,dirtyCheckService){
    $rootScope.$on('$locationChangeStart', function (event, next, prev) {
       if(dirtyCheckService.isFormDirty()){
         event.preventDefault();
       }
    }
})

Of course the above will only work given that you set your form to pristine once the user saves their changes.

like image 28
Mohammad Sepahvand Avatar answered Sep 28 '22 15:09

Mohammad Sepahvand