unconditionalcoder unconditionalcoder - 4 months ago 26
AngularJS Question

AngularJS get id of element clicked and use in controller

I just began learning AngularJS, and I am trying to create a pretty simple web application. Right now, I have some users. Each user is displayed in an individual table and each user has its own details which is displayed in a table under it.
enter image description here

$scope.userList = [{username: "Bob_t", detailsId: 1}, {username: "Mike_V", detailsId: 2}];
$scope.userDetails = [{Name: "Bob", Age: 20, id: "1"}, {Name: "Michael", Age: 18, id: "2"}];


You can see that each user has a reference to it's corresponding details (detailsId in userList corresponds to id in userDetails).

Basically, what I'm trying to do is initially have the details table hidden for each user. And when someone clicks the expand button for a specific user, open that user's corresponding details table and populate it with that user's details. What I'm having trouble with is getting the detailsId from the clicked expand button and then using that to query my DB to get the correct user's details to display in the table under it.

<div ng-repeat="user in userList | filter:searchBox">
<div class="uk-panel-box-secondary uk-overflow-container tableDiv uk-margin-large-bottom">
<table class="uk-table uk-table-hover uk-margin-top">
<thead>
<tr>
<th>Username</th>
</tr>
</thead>
</table>
<a class="uk-margin-bottom uk-margin-left" id="expandIcon" ng-click="isOpened=!isOpened; showOrHideDetails(isOpened, param)" ng-class="{'uk-icon-plus-square-o': !isOpened, 'uk-icon-minus-square-o': isOpened}"></a>
</div>
<div class="uk-panel-box-secondary uk-overflow-container uk-margin-top uk-margin-large-left uk-margin-bottom tableDiv">
<table class="uk-table uk-table-hover uk-margin-top">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th></th>
</tr>
</thead>
<tr ng-repeat="details in userDetails" id={{user.id}}>
<td>{{details.Name}}</td>
<td>{{details.Age}}</td>
<td>
<a href="" class="uk-icon-hover uk-icon-pencil-square-o icons"></a>
<a href="" class="uk-icon-hover uk-icon-trash icons uk-text-danger" ng-click="delete($index)"></a>
</td>
</tr>
</table>
</div>
</div>


my controller:

$http({
method : "GET",
url : "http://database:8081/userAccounts/"
}).then(function mySucces(response) {
$scope.userList = response.data;
}, function myError(response) {
// $scope.userList = response.statusText;
});

$scope.showOrHideDetails = function(isOpened, param)

if(isOpened){
console.log($scope.id)
$scope[id] = true;
console.log($scope.id);
$http({
method : "GET",
url : "http://database:8081/details?id=" + index
}).then(function mySucces(response) {
$scope.userDetails = response.data;
}, function myError(response) {
$scope.userDetails = response.statusText;
});

}
else{
$scope.showDetails = false;
}
}


What is really confusing to me is once I get the correct userDetails object after querying the DB, how do I populate the corresponding table with that info?

I know I probably need a model, but this confuses me because the number of users is unknown.

Answer

First, your code is a bit confuse..

After each query you're attributing the response (which one is the details of a single user) to the whole array userDetails:

$scope.userDetails = response.data;

While it should be:

$scope.userDetails.push(response.data);

In addition, you have a single variable called isOpened, for sure it won't work, because you have multiple buttons for only 1 variable.

So my suggestion is to change it to:

<a class="uk-margin-bottom uk-margin-left" id="expandIcon" ng-click="showOrHideDetails(user)" ng-class="{'uk-icon-plus-square-o': !user.isOpened, 'uk-icon-minus-square-o': user.isOpened}"></a>

Also you have to check if the userDetail is already in your userDetails array.

Finally, since you want to show the details based on the user, you can use the native filter, because you already have the id property of users in both arrays, as below:

<tr ng-if="user.isOpened" ng-repeat="details in userDetails | filter: { id: user.detailsId }" id={{user.id}}>

A simple demo:

(function() {
  angular
    .module('app', [])
    .controller('MainCtrl', MainCtrl);

  MainCtrl.$inject = ['$scope', '$http'];

  function MainCtrl($scope, $http) {
    $scope.userList = [{
      username: "Bob_t",
      detailsId: 1
    }, {
      username: "Mike_V",
      detailsId: 2
    }];
    $scope.userDetails = [{
      Name: "Bob",
      Age: 20,
      id: "1"
    }, {
      Name: "Michael",
      Age: 18,
      id: "2"
    }];

    $scope.showOrHideDetails = function(user) {
      user.isOpened = !user.isOpened;

      function mySuccess(response) {
        $scope.userDetails.push(response.data);
      }

      function myError(response) {
        console.log(response.statusText);
      }
      
      if (user.isOpened) {
        $http.get('http://database:8081/details?id=' + user.id)
          .then(mySuccess)
          .catch(myError);
      } else {
        $scope.showDetails = false;
      }
    }
  }
})();
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.26.4/js/uikit.min.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.26.4/css/uikit.min.css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
</head>

<body ng-controller="MainCtrl">
  <div ng-repeat="user in userList | filter:searchBox">
    <div class="uk-panel-box-secondary uk-overflow-container tableDiv uk-margin-large-bottom">
      <table class="uk-table uk-table-hover uk-margin-top">
        <thead>
          <tr>
            <th>Username</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td ng-bind="user.username"></td>
          </tr>
        </tbody>
      </table>
      <a class="uk-margin-bottom uk-margin-left" id="expandIcon" ng-click="showOrHideDetails(user)" ng-class="{'uk-icon-plus-square-o': !user.isOpened, 'uk-icon-minus-square-o': user.isOpened}"></a>
    </div>
    <div class="uk-panel-box-secondary uk-overflow-container uk-margin-top uk-margin-large-left uk-margin-bottom tableDiv">
      <table class="uk-table uk-table-hover uk-margin-top">
        <thead>
          <tr>
            <th>Name</th>
            <th>Age</th>
            <th></th>
          </tr>
        </thead>
        <tr ng-if="user.isOpened" ng-repeat="details in userDetails | filter: { id: user.detailsId }" id={{user.id}}>
          <td ng-bind="details.Name"></td>
          <td ng-bind="details.Age"></td>
          <td>
            <a href="" class="uk-icon-hover uk-icon-pencil-square-o icons"></a>
            <a href="" class="uk-icon-hover uk-icon-trash icons uk-text-danger" ng-click="delete($index)"></a>
          </td>
        </tr>
      </table>
    </div>
  </div>
</body>

</html>

I hope it helps!!

Comments