boatcoder
boatcoder

Reputation: 18107

How do I show a confirmation dialog from a controller in angular without breaking "the rules"

So I have a user interaction that can perform a task. The task can be initiated with:

  1. A drag and drop,
  2. a keystroke,
  3. A couple of selects and a button press.

The task has a few constraints:

  1. If the user is replacing a previous value (instead of overwriting null), I want to make sure the user meant to do that with a dialog that asks them to confirm the overwrite.
  2. If the UI is stale and someone else has already set the value (value on the server !== null), then I want to fail the operation.

All of this says I need to use a promise, but the first constraint also says I need to put a dialog on the screen. Coming from a mostly jquery background, I don't want to go creating bad angular habits from the beginning, so I'm hoping someone with more than 10 hours of angular under their belt can answer this question.

I can't do it on a directive because it can be activated several different ways. Or maybe I can do it in a directive and just don't know how. To add to the complexity, the source comes from one ng-grid and the destination is a separate ng-grid.

$scope.assignEmployee = function($event) {
    if($scope.selectedEmployee.length && $scope.selectedPosition.length) {
        var position = $scope.selectedPosition[0],
            employee = $scope.selectedEmployee[0];
        if(position.employee) {
            // TODO: Ask the user if they really want to overwrite this

        } else {
            //TODO: Post to the server to see if we can complete this action
            return $http({method: 'POST', url: '/someUrl'}).
                success(function(data, status, headers, config) {
                    // Make the assignment here
                    position.employee = employee;
                }).
                error(function(data, status, headers, config) {
                    $scope.status = "Not today.";
                });
        }
    } else {
        $scope.status = $scope.selectedEmployee.length ? "Select a Position" : "Select an Employee";
    }
};

What I've really got to do is refactor this so the success and error only have to be written once, and the $http call only happens if the user signals YES, or if I never had to ask the user. But What I don't understand his how do I do the dialog interaction from the controller, because that seems to inherently involve DOM manipulation.

Upvotes: 0

Views: 2894

Answers (3)

Kain
Kain

Reputation: 273

Also you can use $broadcast communicate between controller with controller or directive with directive.

App.directive('myEditor',function(){
    return{
       link:function(scope,element,attrs)
       {
            element.bind('keydown',function(){
              scope.$broadcast('text.changed',{});
           }
       }
    }
}

App.directive('myDialog', function() {
    return {
        link: function(scope, element, attrs) {
          scope.$on('text.changed',function(event,args){
             //todo:
          });
        }
    }
});

Upvotes: 0

boatcoder
boatcoder

Reputation: 18107

The best clean example I've found so far for doing this comes from @m.e.conroy (Michael Conroy). He has code here:

Upvotes: 1

Michael Low
Michael Low

Reputation: 24506

I don't really understand the details of your code, but as a general approach to do dialog interaction from the controller without DOM manipulation you can:

  • Use a directive on the dialog HTML
  • In the controller, set a $scope.showDialog = true; (or whatever) variable.

And then watch for this variable in the directive, and act on it when it's changed.

App.directive('myDialog', function() {
    return {
        link: function(scope, element, attrs) {
            scope.$watch('showDialog', function(newValue, oldValue) {
                if (newValue) {
                    // do DOM manipulation here 
                }
            });
        }
    }
});

Upvotes: 0

Related Questions