2015-05-04 21 views
1

我有一个创建多个表单元素一个指令:指令模板内AJAX查询

// 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()";但是,从模板调用它时不起作用。

我已经尝试了许多不同的答案,我在这里找到了,但没有一个按预期的方式工作(如无限$ http调用永远运行),或者如果他们这样做,提交答案的人提供没有评论或其他细节为什么的代码工作,所以我无法适应我的需求。最重要的是,各种方法都使用不同的技术,有些已被弃用,所以没有一致性来确定我需要做什么。

如何从我的指令模板中拨打getProductPrice()


编辑

我创建了一个Plunker证明旧值传递给getProductPrice()方法。

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

回答

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()"> 

UPDATE:如果你想传递的具体参数为这个电话,你可以简单地将它们添加方法签名:

$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}) 

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

+0

我原以为这应该是这么简单,我不明白为什么这么多其他答案让一切变得如此复杂;然而,在这个例子中,请求参数总是旧值而不是新值。 – pspahn

+0

究竟是什么请求参数?它是''$ scope.sku“'?这在你的例子中似乎是一个常量字符串。 – floribon

+0

PS:你发现的复杂答案可能是直接绑定'$ http'调用给诸如“{{getProductPrice()}}”的观察者(因此在每个摘要循环中执行)。这曾经被支持,但不再是通话正在进行(并且正在杀死服务器)。在你的情况下,你只在特定的事件('ng-change')执行调用,所以没关系。 – floribon

0

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

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