我正在调用一个返回一个JavaScript块的字符串的Web服务。除了它有一个众所周知的入口点(function doCalc(input)
)和众所周知的输出(对象数组)之外,我对JavaScript一无所知。 doCalc
我调用的其他函数也会在同一个字符串中返回。
例如,JavaScript字符串可能看起来像这样(简化,但你明白了):
function doCalc(input) {
return calcPart1();
}
function calcPart1() {
var output;
// ...do something complicated
calcPart2(output);
return output;
}
function calcPart2() {
return something;
}
我把这个JavaScript块作为一个字符串,我需要在页面上注入它,并在每次文本框的值发生变化时调用它。 “input”是文本框的值。
我可以通过动态创建脚本元素并将其附加到正文来执行此操作,但无法从我的控制器访问doCalc
。我还想在控制器中访问输出(对象数组),并希望使用ngRepeat绑定它。
处理这种情况的角度最友好的方法是什么?
更新
我现在有两种解决方案,但我对这两种方法都感觉不太好......
解决方案1:将脚本注入DOM,从“onkeyup”调用它并填充绑定到控制器变量的隐藏文本区域。 Fiddle
// In the controller - Download the JavaScript code and inject it into the DOM
// this string would really come as the result of an web service call
$scope.javascriptCode = "function doCalc(input) { ... }";
var script = document.createElement('script');
script.innerHTML = $scope.javascriptCode;
document.body.appendChild(script);
<!-- In the view -->
<!-- Every time the input changes (onkeyup), set the text of a hidden textarea -->
<!-- that is bound to a variable in the controller -->
<input ng-model="scopeInput" onkeyup="handleChange(this.value);" />
<textarea id="outputText" ng-model="myOutput" style="display:none"></textarea>
<script>
function handleChange(val) {
var element = document.getElementById('outputText');
element.value = doCalc(val);
var evt = document.createEvent("HTMLEvents");
evt.initEvent("input", false, true);
element.dispatchEvent(evt);
}
</script>
解决方案2 (来自@ btm1的输入):几乎所有操作都在控制器中使用eval广告附加调用“doCalc”到JavaScript字符串。 Fiddle
// In the controller
// this string would really come as the result of an web service call
$scope.javascriptCode = "function doCalc(input) { ... }";
// watch the input variable and call doCalc whenever it changes
$scope.$watch('myInput', function(newVal, oldVal) {
if (newVal !== oldVal) {
// The code we execute is the code we got back, plus a call to
// doCalc passing in the input.
var codeToRun = $scope.javascriptCode + " doCalc(" + $scope.scopeInput + ");";
$scope.myOutput = eval(codeToRun);
}
<!-- In the view we just have the input -->
<input ng-model="myInput"/>
我倾向于解决方案#2,但我觉得可能有更好的解决方案。