【问题标题】:Calling angular function from swift从swift调用角度函数
【发布时间】:2016-07-29 18:40:54
【问题描述】:

我正在尝试将值从 swift 传递给 angularJS。 下面是调用javascript函数的swift代码:

let userScriptSetToTrue = WKUserScript(
    source: "setTrackingToggleToTrue();",
    injectionTime: WKUserScriptInjectionTime.AtDocumentEnd,
    forMainFrameOnly: true
)
contentController.addUserScript(userScriptSetToTrue)

...
let js = "setTrackingToggleToTrue();"
self.webView?.evaluateJavaScript(js) {
     (_, error) in print(error)
}

然后javascript调用角度控制器函数:

<script>
    function setTrackingToggleToTrue() {
        angular.element(document.getElementById('trackingToggle')).scope().setTracking(true);
    }
</script>

但我在 javascript 端收到以下错误:

TypeError: undefined is not an object (evalating 'angular.element(document.getElementById('trackingToggle')).scope().setTracking')

似乎 document.getElementById('trackingToggle') 不可用,但我可以在 safari 网络检查器元素选项卡中看到以下内容

<div class="list-group-item">
    <tracking-toggle-button
            id="trackingToggle"
            state="trackingEnabled"
            class="pull-right"
            on-toggle="updateTrackingPreference(newState);">
    </tracking-toggle-button>
    <label class="tracking-label">My Location</label>
</div>

这个错误的原因是什么?还是有更好的方法将值从 swift 一直传递到角度控制器?

更新 Angular 应用程序使用 UI 路由并根据路由从不同模板加载页面内容。后来我发现函数 setTrackingToggleToTrue() 在其模板加载之前被调用,因此在函数调用时没有 trackingToggle 可用。是否有另一种方法可以在不引用任何文档元素的情况下在控制器外部调用角度函数?

谢谢。

【问题讨论】:

  • 试试 angular.element(document).find('trackingToggle') 代替document.getElementById('trackingToggle')
  • 我仍然遇到同样的错误:`undefined is not an object (evalating 'angular.element(document).find('trackingToggle').scope().setTracking')

标签: javascript angularjs swift


【解决方案1】:

事实证明 WKWebView.evaluateJavaScript() 只能在顶级范围内调用 javascript。被调用的顶级范围 javascript 不能使用 angular.element() 来调用基于从基于路由的模板加载的元素的角度控制器函数。

我最终使用了一种尴尬的方式来解决它。顶级范围 java 脚本在本地存储中设置切换按钮值,角度控制器功能将检查该值直到它可用。我还必须手动使用 $scope.$apply() 来反映 UI 的变化。

同样可以通过promise 实现。稍后我会尝试 promise 的方式。

【讨论】:

    【解决方案2】:

    请在此处找到工作小提琴:http://jsfiddle.net/varit05/06Ldnys8/25/

    控制器:

    var app = angular.module('app', []).controller('ctrl', function($scope) {
      $scope.inside = { 'name': 'guy', 'idk': 'blah' };
      $scope.abc = function(value) {
        console.log(value);
      }
    });
    
    var getStuff= function() {
      var outside = angular.element(document.getElementById('stuff')).scope().abc('called');
     //console.log(outside.inside)
    }
    

    HTML:

    <div ng-app="app" ng-controller="ctrl" id="stuff">
    </div>
    
    <button onclick="getStuff()">get stuff</button>
    

    希望对你有帮助!

    干杯!

    【讨论】:

    • 感谢您的提琴。我也觉得它应该可以工作,但不知何故我一直收到同样的错误。也许这不是由于 trackingToggle 不可用而是其他原因造成的。
    • 你可以尝试在单引号内调用 true 吗?我也得到了未定义的错误。
    • 我将单引号添加到 true 但没有任何改变。
    • 能否请您发布错误或为您的问题创建一个 plunker?
    • 我添加了对问题的更新。原因是在加载 trackingToggle 元素之前调用了该函数。
    猜你喜欢
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-22
    • 2022-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多