从触发父观察者的子指令调用父指令作用域函数

Calling parent directive scope function from child directive which triggers parent watcher

我有 2 个指令:calculatorFormcalculatorAttribute。 CalculatorForm 是父指令,特别是包含作为 calculatorAttribute 指令的输入标签的表单。

我想要 calculatorAttribute 调用 calculatorForm 函数来更改范围变量并触发观察器。

这是我的代码:

angular
    .module('calculator')
        .directive('calculatorForm', ['CalculatorDataModel', 'CalculatorPriceModel',

            function(CalculatorDataModel, CalculatorPriceModel) {

                return {
                    restrict : 'A',
                    replace : true,
                    templateUrl : function(element, attrs) {
                       return attrs.templateUrl;
                    },
                    link : function(scope, element, attrs) {
                        scope.model = CalculatorDataModel;
                        scope.price = CalculatorPriceModel;
                        scope.model.initialize(calculator_data);

                        scope.updateSelectedSpecs = function(attribute_id, prod_attr_val_id) {

                            var selected_specs = JSON.parse(JSON.stringify(scope.model.selected_specs));
                            selected_specs[attribute_id] = prod_attr_val_id;
                            scope.model.selected_specs = selected_specs;                         
                        }

                        scope.$watch('model.selected_specs', function(selected_specs, previous_selected_specs) {
                            if (selected_specs != previous_selected_specs) {
                                scope.model.setCalculatorData();
                                scope.price.computePrice();
                            }
                        });
                    }
                }
            }
        ])

        .directive('calculatorAttribute', [
            function() {
                return {
                    restrict : 'A',
                    template : "<input type='radio' name='attr{{attribute_id}}' ng-value='prod_attr_val_id'/>",
                    replace : true,
                    link : function(scope, element, attrs) {
                        scope.attribute_id = attrs.attributeId;
                        scope.prod_attr_val_id = attrs.prodAttrValId;

                        element.on('click', function() {
                            scope.$parent.updateSelectedSpecs(scope.attribute_id, scope.prod_attr_val_id);
                        });

                    }
                }

            }
        ]);

我的问题是在父指令中调用了 updateSelectedSpecs,但是当我在子指令中使用 element.on 单击时从未触发观察器。

请大家帮忙谢谢!!!

好吧,经过一番努力之后,我设法生成了精简示例的工作版本:

angular.module('myApp', [])
  .directive('calculatorForm', function() {
    return {
      restrict: 'A',
      replace: true,
      transclude: true,
      template: '<div ng-transclude></div>',
      link: function(scope, element, attrs) {
        scope.model = {};
        scope.price = {};

        scope.updateSelectedSpecs = function(attribute_id, prod_attr_val_id) {
          scope.$apply(function() {
            console.log('update selected specs');
            var selected_specs = {};
            selected_specs[attribute_id] = prod_attr_val_id;
            scope.model.selected_specs = selected_specs;
          });
        }

        scope.$watch('model.selected_specs', function(selected_specs, previous_selected_specs) {
          console.log('new selected specs', selected_specs, previous_selected_specs);
          if (selected_specs != previous_selected_specs) {
            console.log("and they're different");
          }
        });
      }
    };
  })
  .directive('calculatorAttribute', function() {
    return {
      restrict: 'A',
      template: "<input type='radio' name='attr{{attribute_id}}' ng-value='prod_attr_val_id'/>",
      replace: true,
      link: function(scope, element, attrs) {
        scope.attribute_id = attrs.attributeId;
        scope.prod_attr_val_id = attrs.prodAttrValId;

        element.on('click', function() {
          scope.$parent.updateSelectedSpecs(scope.attribute_id, scope.prod_attr_val_id);
        });
      }
    }
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<form calculator-form ng-app="myApp">
  <input calculator-attribute attribute-id=1 prod-attr-val-id=1>
</form>

只需查看控制台即可看到它进入 $watch。问题似乎是您没有在 updateSelectedSpecs 函数中触发 $digest 循环。通常 $timeout$http 调用或 ngClick 或其他事件会为您启动 $digest 循环,但在这种情况下,您必须使用 [=19 自己启动它=].