1

I am trying to learn AngularJS and i am making a test app. I have a table that gets populated with data returned from a WebService (list of publishers) via $http.get().

When the user clicks a row (publisher) i want to fill a second table with the list of employees of the selected publisher. By using the F12 tools (Network+Console) i see that the data is returned but the second table is not filled/updated.

html

<!DOCTYPE html>
<html ng-app="myApp">
<head lang="en">
    <meta charset="UTF-8">
    <link rel="stylesheet" href="css/style.css" type="text/css" />
    <script src=""></script>
    <script src="js/angular.js"></script>
    <script src="js/scripts.js"></script>
    <script src="js/app.js"></script>
    <title>My SPA</title>
</head>
<body>

    <header>
        <h1 id="page-title">Header</h1>
        <nav>
            <ul>
                <a href="#"> <li>Menu 1</li> </a>
                <a href="#"> <li>Menu 2</li> </a>
                <a href="#"> <li>Menu 3</li> </a>
                <a href="#"> <li>Menu 4</li> </a>
            </ul>
        </nav>
    </header>

    <div ng-controller='PublishersController' class="table-wrapper">
        <table class="data-table" />
        <thead>
            <tr>
                <th ng-repeat="(key,val) in publishers[0]">{{key}}</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat='pub in publishers' ng-click='getPublishersEmployees(pub.pub_id)'>
                <td ng-repeat='(key,val) in pub'>{{val}}</td>
            </tr>
        </tbody>
        </table>
    </div>

    <div ng-controller='PublishersController' class="table-wrapper">
        <table class="data-table" />
        <thead>
            <tr>
                <th ng-repeat="(key,val) in employees[0]">{{key}}</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat='employee in employees'>
                <td ng-repeat='(key,val) in employee'>{{val}}</td>
            </tr>
        </tbody>
        </table>
    </div>

</body>
</html>

JS

var urlBase = "http://localhost:2041";

var app = angular.module('myApp', []);

app.factory('myFactory', ['$http', function ($http) {

    var webAPI = '/api/query';
    var webService = urlBase + webAPI;
    var myFactory = {};

    myFactory.getCategories = function () {
        return $http.get(webService + '/getCategories');
    };
    myFactory.getCategorySalesByMonth = function (id) {
        return $http.get(webService + '/getCategorySalesByMonth/' + id);
    };

    myFactory.getPublishers = function () {
        return $http.get(webService + '/getPublishers');
    };
    myFactory.getPublishersEmployees = function (id) {
        return $http.get(webService + '/getPublishersEmployees/' + id);
    };

    return myFactory;
}]);

app.controller('PublishersController', ['$scope', 'myFactory', 
    function ($scope, myFactory) {

    $scope.status;
    $scope.publishers;
    $scope.employees;

    getPublishers();

    function getPublishers() {
        myFactory.getPublishers()
            .success(function (publishers) {
                $scope.publishers = publishers;
            })
            .error(function (error) {
                $scope.status = 'Unable to load publishers data: ' + error.message;
            });
    }

    $scope.getPublishersEmployees = function (id) {
        myFactory.getPublishersEmployees(id)
            .success(function (employees) {
                $scope.employees = employees;
        console.log($scope.employees);
            })
            .error(function (error) {
                $scope.status = 'Error retrieving employees! ' + error.message;
            });
    };
}]);

What am i doing wrong?

3
  • Your template causes two separate controllers, each with its own scope, to be instantiated. You modify the scope of the first controller, but that won't change anything to the scope of the second one. Commented May 9, 2014 at 14:27
  • I use the same controller (PublishersController) in both divs. I edited my post. Commented May 9, 2014 at 14:28
  • 2
    Both controllers have the same type, but there are two different instances of the same controller type. And each instance has its own scope. Controllers are not singletons. Each time you have ng-controller="...", a new scope is created, and a new controller is instantiated. Commented May 9, 2014 at 14:30

1 Answer 1

3

The problem is you use separate controllers for PublishersController and EmployeesController. Angular will create separate scopes for your controllers. Therefore, when you assign $scope.employees = employees in your PublishersController, it does not reflect on the scope created by EmployeesController

Try:

<div ng-controller='PublishersController' class="table-wrapper">
        <table class="data-table" />
        <thead>
            <tr>
                <th ng-repeat="(key,val) in publishers[0]">{{key}}</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat='pub in publishers' ng-click='getPublishersEmployees(pub.pub_id)'>
                <td ng-repeat='(key,val) in pub'>{{val}}</td>
            </tr>
        </tbody>
        </table>

        <table class="data-table" />
        <thead>
            <tr>
                <th ng-repeat="(key,val) in employees[0]">{{key}}</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat='employee in employees'>
                <td ng-repeat='(key,val) in employee'>{{val}}</td>
            </tr>
        </tbody>
        </table>
  </div>

That solution above is just to point out your problem. I don't know your application design, you may not follow this solution but restructure your code to best fit your application design (like storing the employees in a shared service,...).

Here I propose another solution but I'm not sure if it fits with your application. You just use your original HTML code with PublishersController and EmployeesController. In your PublishersController, your could broadcast an event from rootScope:

.success(function (employees) {
             $rootScope.$broadcast("employeeLoaded",employees);
       })

Don't forget to inject $rootScope to your PublishersController:

app.controller('PublishersController', ['$scope', 'myFactory','$rootScope', 
    function ($scope, myFactory,$rootScope)

In your EmployeesController, you could subscribe to this event:

$scope.$on("employeeLoaded",function (event,employees){
     $scope.employees = employees;
});

For more information about event in angular, check out Working with $scope.$emit and $scope.$on

Sign up to request clarification or add additional context in comments.

2 Comments

I use the same controller (PublishersController) in both divs. I messed things up during the copy-paste.
@koukouloforos: I don't know about your application design and all its logic. This answer is just to point out your problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.