AngularJS - 执行动态创建的JavaScript函数

时间:2015-03-27 16:05:15

标签: javascript angularjs

我正在调用一个返回一个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,但我觉得可能有更好的解决方案。

0 个答案:

没有答案