简体   繁体   中英

Angularjs: $watch doesn't work in controller with ngTable

I wrote popup directive for filter of table:

    var ngClass = "{ 'active': itemActive == item }";

    return {
        template: '<span class="header_select_filter">' +
        '<a class="icon icon-filter"></a>' +
        '<div class="large select_popup">' +
        '<h3></h3>' +
        '<div class="content box">' +
        '<ul class="items">' +
        '<li ng-repeat="item in items" ng-class="' + ngClass + '" ng-click="select(item)"><span ng-bind="item.Name"><span></li>' +
        '</ul>' +
        '</div>' +
        '</div>' +
        '</span>',
        replace: true,
        transclude: true,
        scope: {
            items: '=',
            itemActive: '='
        },
        restrict: 'E',
        controller: function ($scope) {
            $scope.select = function (item) {
                $scope.itemActive = item;
            }
        },
        link: function ($scope, $element) {
            var $popup = $element.find('.select_popup');
            $popup.css('top', '50px');
            $popup.find('.content.box').css('padding', '0');

            $element.find('a.icon.icon-filter:first')[0].onclick = function () {
                $popup.toggle();
            };

            $element.find('ul.items')[0].onclick = function () {
                $popup.fadeToggle('slow');
            }

        }
    };


});

Here's how I invoke it:

<select-popup items="filterItems" item-active="type"></select-popup>

And this is code of the angularjs' controller, there are I tried run $watch:

 Invoice.types(function (data) {
            var items = $scope.filterItems = data;

            $scope.type = items[0];
        });

        $scope.$watch('type', function () {

            console.log("type changes");
        });

But $watch('type') don't working, although value of itemActive is updated by click on elements of popup.

Invoice in controller is a service which based on $resourse, ie Invoice.types is ajax request. When I used $http, the problem remains. Can you help me?

EDIT: if I don't used ajax:

 var items = $scope.filterItems = [
         new FilterItem(1, 'Positive'),
         new FilterItem(2, 'Negative'),
         new FilterItem(3, 'Neutral')
    ];

    $scope.type = items[0];

    var i = 1;
    $scope.$watch('type', function () {
        console.log('type changes:' + i);
        i++;
    });

Then it works.

JSFiddle with AJAX works too. Strange why $watch is not working for me.

UPDATE: I found the problem. I'm using ngTable and I put my directive in column of table:

<table ng-table="tableItems">
    <thead>
        <tr>
          <td class="center text-center" rowspan="2">
             <span class="header-name">Name</span>
             <select-popup items="filterItems" item-active="type"></select-popup>       </td>
          <td class="center text-center" rowspan="2">Age</td>
          <td class="center text-center" rowspan="2">Gender</td>
        </tr>
   </thead>

You need to run $apply in each of your onclicks

$element.find('a.icon.icon-filter:first')[0].onclick = function () {
    $popup.toggle();
    scope.$apply();
};

$element.find('ul.items')[0].onclick = function () {
    $popup.fadeToggle('slow');
    scope.$apply();
}

Also, I highly recommend you read up on how to use angular, as you should not be using onclick functions to begin with.

Add in an $apply with your ajax as well.

Invoice.types(function (data) {
        var items = $scope.filterItems = data;

        $scope.type = items[0];
        $scope.$apply();
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM