0

I have written an AngularJS directive for displaying tables. I used these tables on few pages and it wokred awesome, and now I have a page where I need two instances of such table. I am new to AngularJS and maybe it wasn't the best choise in the first place but so far I used the controllers scope for these tables and their directives. And when it comes to having two tables, they act like the same table when I change page for one table, the other one gets its page changed either, because they share the same scope (controller's scope).

I added scope property to the directive declaration to accept items(this should be common for both tables) from the controller and within the directive's controller I declared filteredItems(this should not be common, each table should have its own filtered items list) property of the directive's scope.

Now my controller goes like:

function ($scope, sgtService, ...) {
    sgtService.getList(function (data) {
        $scope.items = data;
    });

    ...
}

My directive declaration is:

abTable: function () {
    return {
        restrict: "A",
        scope: {
            items: '='
        },
        controller: function ($scope, $filter) {
            $scope.filteredItems = [];

            $scope.$watch('items', function () {
                $scope.search();
            });

            $scope.search = function () {
                $scope.filteredItems = $filter("filter")($scope.items, $scope.searchKeywords);
            }

            ...
        }
    };
}

And my HTML is:

<div data-ab-table="" data-items="items">

    ...

    <tbody>
        <tr data-ng-repeat="item in filteredItems">

        </tr>
    </tbody>

    ...

</div>

Directive's controller executes fine like it did before, but my problem is that for some reason in my html I can't access any properties for directive's isolated scope and I can't access these filteredItems. If I replace data-ng-repeat="item in filteredItems" with data-ng-repeat="item in items" it displays the content because the view controller's scope has that property item but it won't iterate through filteredItems which is property of directive's scope. And none other directive's scope properties can be accessed from there, I checked the scope id within the directive html content and it matches the id of the view's controller scope. Why within the directive's html I am dealing with view controller's scope and not with the directive's isolated scope?

2 Answers 2

1

I have slightly tweaked your example, here's the result:

http://jsfiddle.net/nmakarov/E5dm3/4/

Basically, it consists of the following:

  • a mytable directive, it takes items array and produces a table with two rows - original numbers and odd (filtered) numbers
  • a dataProducer service, it produces an array of 10 elements - each one calculates as index times provided multiplier.
  • controller with couple of arrays, couple of multipliers and corresponding watchers.

It works like so: you click on any button, that changes corresponding multiplier, controller's watcher updates corresponding data row, directive's watcher kicks in (because the data row changes) and invokes $scope.search() and that modifies local scope's filteredData property. Two instances of this directive present on the page, and no scope clashing happens.

And if I'm not mistaken, you're trying to access properties belonged to a directive's scope from outside's HTML. That is simply won't work - just no way. If there's something calculated inside your directive and outside world needs to get access to it - move this logic to the controller.

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

1 Comment

Thank you, this helped. What I understood from those two replies is that I should always use template for directives. Actually I was going to move that code to template later, but I didn't know that it matters whether html is in a template or within the directive.
1

I don't think you can access your directive's isolated scope from outside the directive like that. Can you make your directive wrap the table HTML like this:

.directive('abTable', function($filter){
  return {
    restrict: "A",
    replace: true,
    scope: {
      items: '=items',
      searchKeywords: '=searchKeywords' 
    },
    template: '<table><tr data-ng-repeat="item in filteredItems"><td>{{item.id}}</td><td>{{item.value}}</td></tr></table>',
    controller: function ($scope, $filter) {
        $scope.filteredItems = [];

        $scope.$watch('items', function () {
          $scope.search();
        });

        $scope.search = function () {
          $scope.filteredItems = $filter("filter")($scope.items, $scope.searchKeywords);
        }
    }
  };

This example shows two tables using the same items filtered differently.

Comments

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.