在不在指令中使用隔离范围的情况下将值绑定并写回父范围

Binding and writing values back to parent scope without using isolated scope in a directive

在 Angular 中,在没有隔离范围的情况下,将数据传回父范围的首选方法是什么?

假设我有一个指令 x,并且想知道它的值 a,我想做类似的事情:

<x a="some.obj.myA"></x>
current a: {{some.obj.myA}}

我会这样定义 x 指令:

app.directive('x', function() {
    var a = {};
    return {
        restrict: 'E',
        link: function($scope, $element, $attrs) {
            var parentExpression = $attrs.a;

            // ???
        },
        replace: true,
        template: ...
    };
});

现在,我总是想让“$scope.$parent[parentExpression]”(伪代码)等于本地a的值。但是,如果 parentExpression 指的是嵌套对象、数组或任何其他类型的可赋值表达式,这甚至应该有效。

我该怎么做呢?

多个选项:

使用ng-model

示例:

app.directive('x', function() {
  var a = {};
  return {
    require:'ngModel', //require it, you can make it options as well with ?
    restrict: 'E',
    link: function($scope, $element, $attrs, ctrl) {
       var currentValue = ctrl.$viewValue;
       //... do something with the value and then set it back
       ctrl.$setViewValue(newValue);
       ctrl.$render();
    },
    replace: true,
    template: ...
  };
});

<x ng-model="some.obj.myA"></x>

如果您的指令旨在更改模式的值,则可能您正在查看 $formatters/$parsers as well. Also take a look at $viewChangeListeners 如果您打算观察视图值的变化。

 angular.module('app', []).directive('x', function() {
   var a = {};
   return {
     require: 'ngModel', //require it, you can make it options as well with ?
     restrict: 'E',
     link: function($scope, $element, $attrs, ctrl) {
       //override render function
       ctrl.$render = function() {
         var currentValue = ctrl.$viewValue;
         console.log(currentValue);
         //... do something with the value and then set it back
         ctrl.$setViewValue(currentValue + "Updated");
       };
     },
     replace: true,

   };
 });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-init="some={obj:{myA:'hey'}}">
  {{some.obj.myA}}
  <x ng-model="some.obj.myA"></x>
</div>


使用$parse

使用 $parse 服务并根据表达式创建 gettersetter 并将其更新回来。这里可以使用多个属性绑定。

示例:

   link: function($scope, $element, $attrs) {
       var getA = $parse($attrs.a);
       var setA = getter.assign; 
       var currentValue = getter($scope);
       //... update to new value and set it back
       setA ($scope, currentValue  + "Updated")
     },

angular.module('app', []).directive('x', ['$parse', function($parse) {
   var a = {};
   return {
     restrict: 'E',
     link: function($scope, $element, $attrs) {
       var getter = $parse($attrs.a);
       var setter = getter.assign;
       console.log(getter($scope),setter($scope, "Updated"));
     },
     replace: true,

   };
 }]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-init="some={obj:{myA:'hey'}}">
  {{some.obj.myA}}
  <x a="some.obj.myA"></x>
</div>