Monday, November 17, 2014

Angular directive for prompting unsaved changes

0 comments
The best thing about AngularJs is directives, which gives a whole new perspective on customizability and reusability.

One instance that I use andular directives is prompting unsaved changes dialog when doing a back in a detail page. For solving this I coded a small directive which basically hooks in the back button.

For my scenario, in the detail pages there can be multiple forms and editable kendo grids. So I cannot use form's dirty attribute that is exposed by Angular. Therefore I written a checkDirty() method in each controller where I implement this, which encapsulates the logic which decides if there any unsaved changes.

The above method is ideal for me but not for everybody. Some other ways of implementing this is to hook the directive to the form or use directly $dirty attributes available in forms.

Below is the directive that I used to achieve this functionality.

app.directive('ngUnsavedChanges', ['$modal', '$timeout', ($modal, $timeout) => {
        return {
            restrict: 'A',
            link: (scope, element, attrs) => {
                element.bind('click', () => {
                    scope.checkDirty();
                    if (!scope.dirty) { // If view is not dirty do back
                        scope.$apply(attrs.backAction);
                        return;
                    }
                    var modalInstance = $modal.open({
                        templateUrl: 'app/views/savechanges.html',
                        controller: 'CancelConfirmModal',
                        size: 'sm'
                    });
                    modalInstance.result.then(result => {
                        $timeout(() => {
                            if (result === 'save') {
                            scope.$apply(attrs.saveAction);
                            }
                            else if (result === 'dontsave') {
                                scope.$apply(attrs.backAction);
                            }
                        }); 
                    });
                });
            }
        }
    }]);


You can use the directive like this.