3
\$\begingroup\$

I have the following controller:

 angular.module("UserRoles")
.controller("UserRolesController", function($http, $scope){
    $scope.usersearch = "";
    $scope.users = [];
    $scope.roles = {
    }

    $scope.getusers = function(){
        $http.get("/api/finduser/"+$scope.usersearch)
            .success(function(data){
                $scope.users = data;
            });
    }
    // returns ([ [username, userid], ... ])

    $scope.getroles = function($event){
        var uid = $($event.currentTarget).find("a").data("userid");
        $http({
            "method": "GET",
            "url":"/api/rolesbyuser/",
            "params": {"user_dn": uid}
        }).success(function(data){
            console.log(data);
            $scope.roles = data;
        });
        // returns {ldapuser: ldapusername, direct_roles: [r1, r2], inheritedroles: [ir1ir2]}
    };
});

for the following HTML:

<div class="col-lg-3 col-sm-3">
    <form ng-submit="getusers()">
        <div class="form-group">
            <label for="searchf">User Suchen: {{ usersearch }}</label>
            <input ng-model="usersearch" type="text" class="form-control"
                    placeholder="username">
        </div>
    </form>
    <hr/>
    <ul class="list-group">
        <li class="list-group-item text-center user-item"
            ng-repeat="user in users"
            ng-click="getroles($event)">
            <a href="" data-userid="{{ user[1] }}">
                {{ user[0] }}
            </a>

        </li>
    </ul>
</div>

<div class="col-lg-9">
    <div class="well text-center" id="result-well">
        <h4>{{ roles.ldapuser }}</h4>
    </div>
    <div class="panel panel-warning">
        <div class="panel-heading">
            <h3>Direkte Rollen</h3>
        </div>
        <div class="panel-body">
            <div class="list-group">
                <div class="list-group-item"
                     ng-repeat="role in roles.direct_roles track by $index">
                    {{ role }}
                </div>
            </div>
        </div>
    </div>


    <div class="panel panel-success">
        <div class="panel-heading">
            <h3>Vererbte Rollen</h3>
        </div>
        <div class="panel-body">
            <div class="list-group">

                <div class="list-group-item"
                     ng-repeat="role in roles.inherited_roles track by $index">
                    {{ role }}
                </div>
            </div>
        </div>
    </div>

</div>

Everything works fine:

In the form, I search for the user, then I am getting a user list in the format [[user, id] ...] . The site presents the user name and the id is saved in the data attribute of the user. If one clicks on one of the users on the left side, angular fetches the roles for the according user and displays them.

The questions are now:

  1. My click event looks ugly (I use jQuery). What would be the angular way to perform this?

    $($event.currentTarget).find("a").data("userid")
    
  2. Is there an even better way to set the user to be searched for on click?
  3. Should I really use only one controller or should I use one for user and one for roles?

    $($event.currentTarget).find("a").data("userid")
    
\$\endgroup\$
  • \$\begingroup\$ Read this post. It provides a ton of useful advice for thinking in "angular". \$\endgroup\$ – Pete May 29 '15 at 13:00
  • \$\begingroup\$ Thanks, already read that. Which also lead me to the questions above :). Just do not know, how to get rid of the jQuery there \$\endgroup\$ – ProfHase85 May 29 '15 at 13:05
4
\$\begingroup\$

You can access the data by simply passing it into your method call. So instead of passing an event to getroles, just pass the value.

Replace your template:

<ul class="list-group">
        <li class="list-group-item text-center user-item"
            ng-repeat="user in users"
            ng-click="getroles(user[1])">
            <a href="" data-userid="{{ user[1] }}">
                {{ user[0] }}
            </a>
        </li>
    </ul>

Then update your function:

$scope.getroles = function(uid){
    $http({
        "method": "GET",
        "url":"/api/rolesbyuser/",
        "params": {"user_dn": uid}
    }).success(function(data){
        console.log(data);
        $scope.roles = data;
    });
    // returns {ldapuser: ldapusername, direct_roles: [r1, r2], inheritedroles: [ir1ir2]}
};

Using a Service

Sometimes it's good to separate your $http calls to a service. This allows you to re-use your $http calls in other controllers. It seems like overkill, but it helps with re-use. Alternatively, you could use the $resource, which will build the service for you automatically. Unfortunately, in your case, your endpoints are different, so you'll need to roll your own service.

Each method in the service will return a promise so that future controllers can customize the success conditions.

The bonus of this is that it makes it easier to test your controller as you can easily mock out the service. You could've mocked out the $http service, but then your implementation would start to leak into your tests.

I would also recommend having the userSearch being passed into getUser as a parameter. This reduces the amount of state that your controller needs to maintain.

angular.module("UserRoles")
.service("UserRolesService", function($http) {

    this.getUsers = function(userId) {
        return $http.get("/api/finduser/" + userId);
    }

    this.getRoles = function(uid) {
        return $http.get("/api/rolesbyuser/", { params : { "user_dn" : uid } });

    }
})
.controller("UserRolesController", function($scope, UserRolesService) {

    $scope.usersearch = "";
    $scope.users = [];
    $scope.roles = {};

    $scope.getUsers = function(userId) {
        UserRolesService.getUsers(userId).success( function(data) {
            $scope.users = data;
        });
    };

    $scope.getRoles = function(uid) {
        UserRolesService.getRoles(uid).success(function(data) {
            console.log(data);
            $scope.roles = data;
        });
    };

});
\$\endgroup\$
  • \$\begingroup\$ Sorry, you're right, so I do not need the data attribute at all :) Is the rest of the design okay? \$\endgroup\$ – ProfHase85 May 29 '15 at 13:19
  • \$\begingroup\$ It's alright, although some people like to bundle $http calls into a service.. I'll update the answer with that. \$\endgroup\$ – Pete May 29 '15 at 13:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.