AngularJS:从控制器访问指令数据

AngularJS:从控制器访问指令数据,angularjs,angularjs-directive,angularjs-scope,Angularjs,Angularjs Directive,Angularjs Scope,假设我有一个如下所示的AngularJS指令: app.directive('psDIR', [ function() { return { template: "<div style='padding: 5px; border: 1px solid red; margin-bottom: 10px;'><p>This is a direcive:</p> <textarea rows='5' cols='

假设我有一个如下所示的AngularJS指令:

app.directive('psDIR', [
    function() {
        return {
            template: "<div style='padding: 5px; border: 1px solid red; margin-bottom: 10px;'><p>This is a direcive:</p> <textarea rows='5' cols='50' ng-model='md'></textarea></div>",
            restrict: 'AEC',
            scope: {}
        }
    }
]);
Plunker演示:


非常感谢您的建议。

因为您正在创建独立的作用域,否则您也无法从父作用域访问子作用域

解决方法是将模型作为参数从类父对象传递


然后在指令中使用属性绑定更新它们。请参阅更新plunkr


一个可能的解决方案是使用
require

app.directive('psDIR', [
    function() {
        return {
            ...,
            require: "ngController",
            link: function(scope, elem, attrs, ngCtrl) {
              ngCtrl.hook(scope);
            }
        }
    }
]);
以及对控制器进行必要的更改:

app.controller('MainCtrl', ['$scope',
    function($scope) {
        console.log("init");
        $scope.add = function() {
            var i;
            for( i=0; i < psDirs.length; i++ ) {
              console.log(i + " -> " + psDirs[i].md);
            }
        }

        var psDirs = [];
        this.hook = function(scope) {
          psDirs.push(scope);
        };
    }
]);
指令本身使用上一个ng控制器的代码:

app.directive('wrapperDirective', function() {
    return {
        restrict: "A",
        // YOU MAY WANT ISOLATED SCOPE, JUST ADD scope: {},
        controller: ["$scope", function($scope) {
            // SAME CODE AS BEFORE
            console.log("init");
            $scope.add = function() {
                var i;
                for( i=0; i < psDirs.length; i++ ) {
                  console.log(i + " -> " + psDirs[i].md);
                }
            }

            var psDirs = [];
            this.hook = function(scope) {
              psDirs.push(scope);
            };
        }]
    };
});

当您想要在作用域(即指令和其他控制器)之间通信时,通常正确的做法是使用服务

您可以在此处查看一个简单的plunker:

psDirs
服务保留指令的注册表:

app.service('psDirs', function() {
  var psDirs = {
    dirs: [],
    register: function (dir) {
      psDirs.dirs.push(dir);
    }
  };

  return psDirs;
});
指令会自动注册并在更改时更新值:

link: function (scope, elm, attr) {
  var dir = { val: "" };
  psDirs.register(dir);

  scope.$watch('md', function (n, o) {
    if (n !== o) {
      dir.val = n;
    }
  });
}

然后,控制器可以注入psDirs服务,并根据需要访问指令注册表。这可以防止脆弱的范围关系,并允许在其他地方使用指令注册表服务,在应用程序的多个控制器和部分中。

请详细了解包装器控制器的详细信息。
wrapperDirectiveCtrl
comming from在哪里?它是
wrapperDirective
的控制器。这是一种命名约定。临界值在
要求中:“XXX”
,其中
XXX
必须与指令名称匹配。是的,这是正确的。此外,您可能需要许多控制器。我在上面的语法中有一个错误,正确的是
require:“^wrapperDirective”
(意思是搜索我的父母以查找指定的指令)-我将在答案中更正它。阅读详细信息。此解决方案清晰有效,易于理解。然而,我忍不住认为AngularJS团队已经看到了这种情况,他们实施了这种情况——我只是没有意识到!)在国际海事组织(IMO)看来,在服务中保持这样的状态通常是一个坏主意——如果有的话,必须谨慎行事。例如,上面的代码从未从服务中注销指令数据,这意味着它从未被垃圾收集,随着时间的推移,随着指令的销毁和重新创建,服务将积累越来越多的冗余数据。以及应用程序无意中重复使用“死”数据的风险,如果您碰巧注册了包含关闭的任何内容,您可能会导致相当严重的内存泄漏!这是我第一次在指令上看到模型。你能给我提供一个链接,也许我可以在那里多读一些书。这是我随便取的名字。你可以取任何名字。阅读指令api的编译文档此解决方案看起来最干净。让我做一些实验。
app.directive('psDIR', [
    ...
    require: "^wrapperDirective",
    link: function(scope, elem, attrs, wrapperDirectiveCtrl) {
        wrapperDirectiveCtrl.hook(scope);
    }
app.service('psDirs', function() {
  var psDirs = {
    dirs: [],
    register: function (dir) {
      psDirs.dirs.push(dir);
    }
  };

  return psDirs;
});
link: function (scope, elm, attr) {
  var dir = { val: "" };
  psDirs.register(dir);

  scope.$watch('md', function (n, o) {
    if (n !== o) {
      dir.val = n;
    }
  });
}