AngularJS指令不更新

时间:2017-05-24 01:48:43

标签: javascript angularjs angularjs-directive angularjs-scope

我有一个指令似乎在Angular实例化页面时正确设置了所有内容,但在与其组件交互时不会更新。

HTML:

<div class="app-table col-md-6 col-sm-12 col-xs-12" app-table>
    <header>
        <span class="col-xs-12">Subscriptions</span>
    </header>
    <div class="pagination">
        <span class="user-controls">
            <span class="page-down glyphicon glyphicon-chevron-left"></span>
            <input type="text" ng-model="page"/>
            <span>/ {{summary.subscriptions.pages}}</span>
            <span class="page-up glyphicon glyphicon-chevron-right"></span>
        </span>
        <span class="results-text">Results 1 - {{summary.subscriptions.labels.length}} of {{summary.subscriptions.total}}</span>
    </div>
    <table class="col-xs-12 table-striped">
        <thead>
            <td class="col-xs-9">Name</td>
            <td class="col-xs-3">Subscribers</td>
        </thead>
        <tbody>
            <tr ng-repeat="label in summary.subscriptions.labels | limitTo: 5 : offset">
                <td class="col-xs-9">{{label.name}}</td>
                <td class="col-xs-3">{{label.subscribers}}</td>
            </tr>
        </tbody>
    </table>
</div>

控制器:

app.controller('DashboardCtrl', ['$scope', 'DashboardService', function($scope, DashboardService) {
    $scope.summary = {};

    $scope.init = function() {
        DashboardService.getSummary().then(function(response){
            $scope.summary = response;
        });
    };

    $scope.init();
}]);

指令:

app.directive('appTable', [function () {
return {
    restrict: 'A', 
    scope: true,
    link: function (scope, elem) {
        scope.offset = 0;
        scope.page = 1;

        elem.find('.page-up').bind('click', function(){
            scope.offset += 5;
            scope.page += 1;
        });


        elem.find('.page-down').bind('click', function(){
            scope.offset -= 5;
            scope.page -= 1;
        });
    }
};
}]);

当页面加载时,它正确显示页面1,偏移量为0.如果我将变量更改为page = 2且offset = 5,则页面加载为预期,正确填充值,并正确偏移显示索引6-10的订阅。但是,当我单击单击元素绑定的按钮时,我看不到页面或偏移变量更新,即使我可以通过Chrome开发工具验证点击绑定是否被点击。似乎指令没有正确地将范围变量传递给父控制器?

2 个答案:

答案 0 :(得分:0)

我认为你有两个不同的问题。

第一个问题是你在Angular之外调用一个点击处理程序,所以它不知道它需要运行它的摘要周期。您可以在ng-clickpage-up元素上附加page-down,或致电$apply来解决此问题:

elem.find('.page-up').bind('click', function(){
    scope.$apply(function () {
        scope.offset += 5;
        scope.page += 1;
    });
});

第二个问题是你的指令有scope: true,这意味着它通过原型继承来支持父(控制器)范围。因此,当您的指令开始将pageoffset设置到作用域上时,它会在其自己的作用域上创建新变量,而控制器等任何外部作用域都看不到:

link: function (scope, elem) {
    // Creating new variables on the child scope

    scope.offset = 0;
    scope.page = 1;

    elem.find('.page-up').bind('click', function(){
        // Updating variables on the child scope

        scope.offset += 5;
        scope.page += 1;
    });
}

因此,如果您在{{ page }}元素中添加{{ offset }}app-table标记,您会看到它更新。但是,如果您在app-table元素之外添加该标记(但仍在ng-controller元素内),您将看到控制器没有新信息。

如果设置scope: false,它应该有效,因为那时你将写入与控制器相同的确切范围。

如果您在控制器中使用对象,它可以与scope: true一起使用:

scope.pagination = {
    offset: 0;
    page: 1
};

此外,我不确定此处提供的示例是否已简化,但您基本上使用Angular指令来执行jQuery。您是否考虑使用pagination(隔离范围)创建独立的scope: "="组件?然后,您可以明确传入所需的数据(pageoffsettotal,。etc),并且该指令可以拥有自己的模板。

答案 1 :(得分:0)

jquery中使用angularjs仍然存在问题。

事实上,offsetpage已在您的范围内进行了更改,但如果您想在视图中反映这些内容,则必须致电scope.$apply()让角度重新呈现您的网页。

&#13;
&#13;
var app = angular.module("app", []);
app.controller('DashboardCtrl', ['$scope', function($scope) {
  $scope.summary = {
    subscriptions: {
      labels: [
        {
          name: 'name1',
          subscribers: 'A,B'
        },{
          name: 'name2',
          subscribers: 'A,B,C'
        },{
          name: 'name3',
          subscribers: 'A,B,C,D'
        }
      ],
      total: 10,
      pages: 1
    }
  };
  
  //$scope.offset = 0;
  //$scope.page = 1;
}]);

app.directive('appTable', [function() {
  return {
    restrict: 'A',
    scope: true,
    link: function(scope, elem) {
      scope.offset = 0;
      scope.page = 1;
      elem.find('.page-up').on('click', function() {
        scope.$apply(function() {
          scope.offset += 5;
          scope.page += 1;
        });
      });


      elem.find('.page-down').on('click', function() {
        scope.$apply(function() {
          scope.offset -= 5;
          scope.page -= 1;
        });
      });
    }
  };
}]);
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="app" ng-controller="DashboardCtrl">
  <div class="app-table col-md-6 col-sm-12 col-xs-12" app-table>
    <header>
      <span class="col-xs-12">Subscriptions</span>
    </header>
    <div class="pagination">
      <span class="user-controls">
            <span class="page-down glyphicon glyphicon-chevron-left">PageDown</span><br>
      <input type="text" ng-model="page" />
      <span>/ {{summary.subscriptions.pages}}</span><br>
      <span class="page-up glyphicon glyphicon-chevron-right">PageUp</span><br>
      </span>
      <span class="results-text">Results 1 - {{summary.subscriptions.labels.length}} of {{summary.subscriptions.total}}</span>
    </div>
    <table class="col-xs-12 table-striped">
      <thead>
        <td class="col-xs-9">Name</td>
        <td class="col-xs-3">Subscribers</td>
      </thead>
      <tbody>
        <tr ng-repeat="label in summary.subscriptions.labels | limitTo: 5 : offset">
          <td class="col-xs-9">{{label.name}}</td>
          <td class="col-xs-3">{{label.subscribers}}</td>
        </tr>
      </tbody>
    </table>
    {{offset}}
    {{page}}
  </div>
&#13;
&#13;
&#13;