指令模板内的AJAX查询

时间:2015-05-04 22:58:02

标签: angularjs angularjs-directive

我有一个创建多个表单元素的指令:

// Directive
app.directive('comboInput', function(){
    return {
        scope: {
            imodel: '=',
            dmodel: '=',
            bmodel: '=',
            inputname: '@',
            integers: '=',
            decimals: '='
        },
        templateUrl: templatePath + 'combo-input.html'
    }
});

// Template
<select id="" ng-model="imodel" ng-change="bmodel=imodel+dmodel" ng-options="value for value in integers"></select>
<select id="" ng-model="dmodel" ng-change="bmodel=imodel+dmodel" ng-options="(value|fraction) for value in decimals"></select>
<input type="number" name="{{inputname}}" ng-model="bmodel">

// Usage
<combo-input inputname="width" bmodel="width" imodel="widthI" dmodel="widthD" integers="ints" decimals="decs"></combo-input>

此应用程序的控制器有一种获取价格的方法:

$scope.getProductPrice = function(){
    return $http.post('/customize/angular/getProductPrice', {
        sku: '$scope.sku',
        width: $scope.width,
        height: $scope.height
    }).then(function(response){
        $scope.productPrice = parseFloat(response.data).toFixed(2);
    });
}

我在表单的各个部分使用此方法,通常通过在某个表单元素上调用ng-change="getProductPrice()";但是,从模板中调用它时,这不起作用。

我已经在SO上找到了许多不同的答案,但是没有一个像预期的那样工作(比如永远运行的无限$ http电话),或者如果他们这样做,提交答案的人提供的不是关于为什么代码的评论或其他详细信息,因此我无法适应我的需求。除此之外,各种方法都使用不同的技术,有些方法已被弃用,因此找出我需要做的事情没有一致性。

如何从我的指令模板中调用getProductPrice()

修改

我创建了一个Plunker来演示传递给getProductPrice()方法的旧值。

http://plnkr.co/edit/1nRs26nTaSOztjvVyLYg?p=preview

2 个答案:

答案 0 :(得分:1)

您的指令具有隔离范围(scope: {...}),因此它无法访问上层控制器范围的变量和方法,例如getProductPrice

您可以做的是将此方法作为参数传递给您的指令:

app.directive('comboInput', function () {
  return {
    scope: {
      imodel: '=',
      dmodel: '=',
      bmodel: '=',
      inputname: '@',
      integers: '=',
      decimals: '=',
      on-change: '&'
    },
    templateUrl: templatePath + 'combo-input.html'
  }
});

然后你会像这样实现:

<combo-input ... on-change="getProductPrice()"></combo-input>

然后你只需要从你的指令中调用scope.onChange()来调用已经绑定到on-change属性的这个函数。

或者您甚至可以直接将其绑定到内置ng-change

<input ... ng-change="onChange()">

更新:如果您要为此调用传递特定参数,只需将其添加到方法签名中即可:

$scope.getProductPrice = function(width, height) { ... }

并且还在指令绑定中:

<combo-input ... on-change="getProductPrice(width, height)"></combo-input>

然后您需要做的就是使用这些参数调用onChange。如果您在HTML中编写它,它就像:

一样简单
<input ng-change="onChange(width, height)">

(确保widthheight明显在您的指令范围内,以便可以在HTML中使用。

如果您想从代码中调用该代码,则widthheight已经在您的范围内,在这种情况下,您只需要致电scope.onChange()。但是,如果不是,则可以使用以下特定语法为此调用添加这些参数:

scope.onChange({width: value1, height:value2})

另一种方法是使这个Ajax方法成为服务而不是控制器功能。通过在您的指令中注入服务,您可以直接调用myService.getProductPrice()。参数绑定的优点是您可以使用不同的行为重用您的指令,但如果它总是调用该函数,那么首选服务。

答案 1 :(得分:0)

由于您将指令的范围声明为新指令,因此您声明的条目将绑定在此范围与外部(使用其中的方法)之间。

您可以使用指令定义对象的scope散列将函数传递给指令作用域,也可以在指令中添加另一个具有相同控制器的ng-controller。