从指令更新范围变量

时间:2014-01-19 17:59:12

标签: angularjs angularjs-directive angularjs-scope

指令更新的范围变量不会反映在页面上{{variable}}的位置,但是当我执行console.log(scope)时它们会显示为更新。

<script>
    var demoApp = angular.module('demoApp', []);

    demoApp.controller('demoController', function demoController($scope) {
      $scope.myElementId ="abcd";
      $scope.updateVals = function() {
        $scope.myElementClass = "";
      };
    });

    demoApp.directive('demoSelect', function() {
      return {
        restrict: 'A',
        controller: 'demoController',
        link: function(scope, element, attrs, controller) {
          element.on("click", function(event) {
            event.stopImmediatePropagation();
            event.preventDefault();
            scope.ele = angular.element(event.target);
            angular.element(".selected").removeClass("selected");
            $(scope.ele).addClass("selected");
            var mm = $(scope.ele).get(0);
            scope.myElementId = $(scope.ele).attr("id");
            scope.myElementClass = $(scope.ele).attr("class");
            scope.myElementType = mm.tagName;
          });
        }
      };
    });
  </script>

Here is the plunker。我错过了什么?

3 个答案:

答案 0 :(得分:6)

您的演示中有几个错误:

  1. jQuery在 Angular之后加载。你应该总是在Angular之前加载jQuery,所以后者知道并且可以利用前者。

  2. 自动划线分隔到camelCase转换仅适用于指令,应用程序或控制器的名称。因此,您应该在HTML中编写demoAppdemoController,而不是demo-appdemo-controller

  3. 您正在从非Angular上下文(jQuery事件回调)调用一些特定于Angular的代码(更新Scope中的值),因此为了让Angular处理更改(并将结果传播到您必须将相关代码包含在 scope.$apply() 中。

  4. (技术上这不是错误,但是):您正在将一些jQuery对象再次转换为jQuery对象。这会引入不必要的开销,应该避免。


  5. 考虑到上述情况,你的指令的链接功能的主体应该是这样的:

    element.on('click' , function(evt) {
        evt.stopImmediatePropagation();
        evt.preventDefault();
    
        $('.selected').removeClass('selected');
        element.addClass('selected');
        scope.$apply(function () {
            scope.myElementId    = attrs.id;
            scope.myElementClass = attrs.class;
            scope.myElementType  = element.prop('tagName');
        });
    });
    

    另请参阅此 woking demo

答案 1 :(得分:4)

使用scope.$apply

scope.$apply(function(){
    scope.ele = angular.element(event.target);
    angular.element(".selected").removeClass("selected");
    $(scope.ele).addClass("selected");
    var mm = $(scope.ele).get(0);
    scope.myElementId = $(scope.ele).attr("id");
    scope.myElementClass = $(scope.ele).attr("class");
    scope.myElementType = mm.tagName;
});

你需要这个,因为你正在修改事件中的范围变量,而在这种情况下angularjs不会更新dom

答案 2 :(得分:2)

您的链接功能应如下所示:

link: function(scope, element, attrs, controller) {
      element.on("click", function(event) {

        event.stopImmediatePropagation();
        event.preventDefault();

        $(".selected").removeClass("selected");
        $(element).addClass("selected");

        var mm = $(element).get(0);
        scope.myElementId = $(element).attr("id");
        scope.myElementClass = $(element).attr("class");
        scope.myElementType = mm.tagName;

      });
    }

您的代码中也有错误。处理控制器和应用程序的camelcase名称。