1

Lets say I have the following view code:

<button ng-click="login()">Login</button>

If I would like to pass a callback from the view into the controllers login method, how would I do that?

I want to do something like:

<button ng-click="login( function() { 
                           $('#loginDialog').modal('hide'); 
                         } )">Log in</button>

But angular won't parse that code in ng-click so it won't work.

What I want to do is to separate out DOM manipulation from the controllers and into callbacks that the controllers can call. Thus, making the controller more testable.

I do know there is a dialog service for angular but lets pretend the usecase isn't dialogs, just some other DOM altering stuff.

Do I have to resort to service injection and register all callbacks in a service and inject that service into my controller? I would like to have the injection as method injection instead of constructor injection here.

So is there any way to do something like what I've described above?

Roger Johansson
  • 22,764
  • 18
  • 97
  • 193

2 Answers2

0

In angular, the preferred way of doing DOM manipulation is to use directives... or to bind your view logic with directives like ng-show or ng-hide

Just create a directive to wrap your modal window with, or use angular ui bootstrap's $dialog service.. which is an excellent one.

Shai Reznik - HiRez.io
  • 8,748
  • 2
  • 33
  • 33
  • I know how to use ng-show and hide, but in a case where there are no model state for the change, e.g it would be plain ugly to have a boolean in the model for "isLoggingIn" that controlls the visibillity of the login form/dialog/div/whatever in such case, I would like to make the change via code, from the controller.. even with directives I do not see how I can pass callbacks to my controller functions – Roger Johansson Jul 05 '13 at 08:28
  • The use of "isLoggingIn" boolean is the "Angular way", because you can easily be tested within the controller, and it's really hard to test jQuery logic within the views, it also took me a while to get use to the "angular way" but it is their recommendation for separating view from logic, and from my experience it make sense in unit tests – Shai Reznik - HiRez.io Jul 05 '13 at 08:33
  • the dialog service in angular don't rely on any fugly isLoggingIn state littering your model, so the .close function on the dialogs in $dialog service are abstracting away the dom manipulation the same way I suggest. their code will do a .modal('hide') somewhere I guess.. – Roger Johansson Jul 05 '13 at 08:40
  • The $dialog service don't hide or show, it actually removes or adds the modal window to the dom, and yeah, that's the only use case they mention where they used dom manipulation in services (not in controllers), only for modal windows, I thought you were asking about controllers or altering the DOM, almost every other use case I encountered can be solved with directives – Shai Reznik - HiRez.io Jul 05 '13 at 09:02
0

I ended up doing it with a service:

app.service('userEvents', function () {
    this.loggedIn = function () {
        $('#loginDialog').modal('hide');
    };
    this.registered = function () {
        $('#registerDialog').modal('hide');
    };
});

After thinking about this, it has nothing to do with DOM or angular or the angular way. Closing the login form is a side effect of the user logging into the system.

Thus. I created an event service for users. So The controller can notify the service when a user have logged in or registered etc.

And the service can then decide what to do when such event occured. e.g. sending emails, closing the dialog or other behavior that don't have anything to do with the model itself.

Roger Johansson
  • 22,764
  • 18
  • 97
  • 193