从指令更新作用域变量

4
指令更新的作用域变量在页面上的{{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>

这里是 Plunker 的链接。我错过了什么吗?


1
https://dev59.com/gWkw5IYBdhLWcg3wu9Fg#9693933 - StarsSky
你缺少一个没有错误的 Plunker。 - Stewie
3个回答

6

您的演示中有几个错误:

  1. jQuery在Angular之后加载。您应该始终在Angular之前加载jQuery,这样后者才能意识到并利用前者。

  2. 自动短横线转换为驼峰式仅适用于指令名称,而不适用于应用程序或控制器的名称。因此,在HTML中,您应编写demoAppdemoController,而不是demo-appdemo-controller

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

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


考虑到以上内容,您的指令链接函数主体应该如下所示:

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');
    });
});

请查看这个实际演示


在我的本地开发环境中,除了缺少scope.$apply之外,所有问题都没有出现。感谢您指出其他问题。 - Vikram
还有一个小问题-我该如何在iFrame上下文中为动态元素使其工作(您已经看到跨iframe拖放的情况)。我尝试了很多方法,但似乎还是缺少一些非常基础的东西。 - Vikram
我认为不需要任何花哨的东西。确保在iframe中有适当的CSS样式,并在iframe的上下文中编译投放的元素。 - gkalpak
我可以请求您查看这里的代码 - http://78.110.163.229/ang/select/outer.html。选择指令在iFrame外部运行得很完美,但在iFrame内部却不起作用。我已经在“stop”函数中附加了拖动元素的onclick事件,并编译了iframeBody,但点击事件仍然无法触发。 - Vikram

4

Use 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
您的链接函数应该如下所示:
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;

      });
    }

你的代码中有一个错误。请注意控制器和应用程序的驼峰命名方式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接