136

我正在尝试查看是否有一种简单的方法可以通过外部 javascript 函数访问控制器的内部范围(与目标控制器完全无关)

我在这里看到了其他几个问题

angular.element("#scope").scope();

将从 DOM 元素中检索范围,但我的尝试目前没有产生正确的结果。

这是jsfiddle:http: //jsfiddle.net/sXkjc/5/

我目前正在经历从普通 JS 到 Angular 的过渡。我试图实现这一目标的主要原因是尽可能保持我的原始库代码完整;节省了我将每个功能添加到控制器的需要。

关于如何实现这一目标的任何想法?也欢迎对上述小提琴发表评论。

4

12 回答 12

230

如果要从 angularjs 的控制之外(如 jquery/javascript 事件处理程序)对范围值进行任何更改,则需要使用$scope.$apply() 。

function change() {
    alert("a");
    var scope = angular.element($("#outer")).scope();
    scope.$apply(function(){
        scope.msg = 'Superhero';
    })
}

演示:小提琴

于 2013-03-15T04:54:24.063 回答
26

自从我发布这个问题以来已经有一段时间了,但考虑到这似乎仍然得到的观点,这是我在过去几个月中遇到的另一个解决方案:

$scope.safeApply = function( fn ) {
    var phase = this.$root.$$phase;
    if(phase == '$apply' || phase == '$digest') {
        if(fn) {
            fn();
        }
    } else {
        this.$apply(fn);
    }
};

上面的代码基本上创建了一个safeApply调用该函数的$apply函数(如 Arun 的回答中所述),如果且只有 Angular 当前没有通过$digest阶段。另一方面,如果 Angular当前正在消化东西,它会按原样执行函数,因为这足以向 Angular 发出信号以进行更改。

$apply在 AngularJs 当前处于其$digest阶段时尝试使用该功能时会发生许多错误。上面的safeApply代码是防止此类错误的安全包装器。

(注意:为了方便起见safeApply,我个人喜欢加入)$rootScope

例子:

function change() {
    alert("a");
    var scope = angular.element($("#outer")).scope();
    scope.safeApply(function(){
        scope.msg = 'Superhero';
    })
}

演示:http: //jsfiddle.net/sXkjc/227/

于 2013-08-16T03:19:09.173 回答
17

另一种方法是:

var extScope;
var app = angular.module('myApp', []);
app.controller('myController',function($scope, $http){
    extScope = $scope;
})
//below you do what you want to do with $scope as extScope
extScope.$apply(function(){
    extScope.test = 'Hello world';
})
于 2015-06-23T01:06:21.680 回答
13

我们可以在加载后调用它

http://jsfiddle.net/gentletech/s3qtv/3/

<div id="wrap" ng-controller="Ctrl">
    {{message}}<br>
    {{info}}
    </div>
    <a  onClick="hi()">click me </a>

    function Ctrl($scope) {
        $scope.message = "hi robi";
        $scope.updateMessage = function(_s){
            $scope.message = _s;    
        };
    }

function hi(){
    var scope = angular.element(document.getElementById("wrap")).scope();
        scope.$apply(function() {
        scope.info = "nami";
        scope.updateMessage("i am new fans like nami");
    });
}
于 2013-09-12T07:52:00.600 回答
8

我已经很久没有问这个问题了,但这里有一个不需要 jquery 的答案:

function change() {
    var scope = angular.element(document.querySelector('#outside')).scope();
    scope.$apply(function(){
        scope.msg = 'Superhero';
    })
}
于 2014-07-28T07:10:27.590 回答
3

这是一个可重复使用的解决方案:http: //jsfiddle.net/flobar/r28b0gmq/

function accessScope(node, func) {
    var scope = angular.element(document.querySelector(node)).scope();
    scope.$apply(func);
}

window.onload = function () {

    accessScope('#outer', function (scope) {
        // change any property inside the scope
        scope.name = 'John';
        scope.sname = 'Doe';
        scope.msg = 'Superhero';
    });

};
于 2015-09-08T11:37:25.023 回答
2

你也可以试试:

function change() {
    var scope = angular.element( document.getElementById('outer') ).scope();
    scope.$apply(function(){
        scope.msg = 'Superhero';
    })
}
于 2016-09-06T10:19:52.593 回答
1

接受的答案很棒。我想看看 Angular 范围在ng-repeat. 问题是,Angular 将为每个重复的项目创建一个子范围。当调用在 original 上定义的方法时$scope,它会保留其原始值(由于 javascript 闭包)。但是,this指的是调用范围/对象。这很有效,只要你清楚什么时候$scopethis什么时候是一样的,什么时候是不同的。hth

这是一个说明差异的小提琴:https ://jsfiddle.net/creitzel/oxsxjcyc/

于 2015-05-07T14:45:37.373 回答
1

我是新手,如果是不好的做法,很抱歉。根据选择的答案,我做了这个功能:

function x_apply(selector, variable, value) {
    var scope = angular.element( $(selector) ).scope();
    scope.$apply(function(){
        scope[variable] = value;
    });
}

我这样使用它:

x_apply('#fileuploader', 'thereisfiles', true);

顺便说一句,对不起我的英语

于 2016-08-02T05:07:39.023 回答
0
<input type="text" class="form-control timepicker2" ng-model='programRow.StationAuxiliaryTime.ST88' />

访问范围值

假设 programRow.StationAuxiliaryTime 是一个对象数组

 $('.timepicker2').on('click', function () 
    {
            var currentElement = $(this);

            var scopeValues = angular.element(currentElement).scope();
            var model = currentElement.attr('ng-model');
            var stationNumber = model.split('.')[2];
            var val = '';
            if (model.indexOf("StationWaterTime") > 0) {
                val = scopeValues.programRow.StationWaterTime[stationNumber];
            }
            else {
                val = scopeValues.programRow.StationAuxiliaryTime[stationNumber];
            }
            currentElement.timepicker('setTime', val);
        });
于 2015-06-30T05:16:23.843 回答
0

我们需要使用 Angular Js 内置函数$apply来访问控制器函数之外的范围变量或函数。

这可以通过两种方式完成:

|*| 方法 1:使用 Id:

<div id="nameNgsDivUid" ng-app="">
    <a onclick="actNgsFnc()"> Activate Angular Scope</a><br><br>
    {{ nameNgsVar }}
</div>

<script type="text/javascript">

    var nameNgsDivVar = document.getElementById('nameNgsDivUid')

    function actNgsFnc()
    {
        var scopeNgsVar = angular.element(nameNgsDivVar).scope();
        scopeNgsVar.$apply(function()
        {
            scopeNgsVar.nameNgsVar = "Tst Txt";
        })
    }

</script>

|*| 方法 2:使用 ng-controller 的 init :

<div ng-app="nameNgsApp" ng-controller="nameNgsCtl">
    <a onclick="actNgsFnc()"> Activate Angular Scope</a><br><br>
    {{ nameNgsVar }}
</div>

<script type="text/javascript">

    var scopeNgsVar;
    var nameNgsAppVar=angular.module("nameNgsApp",[])
    nameNgsAppVar.controller("nameNgsCtl",function($scope)
    {
        scopeNgsVar=$scope;
    })

    function actNgsFnc()
    {
        scopeNgsVar.$apply(function()
        {
            scopeNgsVar.nameNgsVar = "Tst Txt";
        })
    }

</script>
于 2018-03-23T18:25:02.820 回答
0

这就是我CRUDManager class在 Angular 控制器中初始化时所做的,后来传递给控制器​​外部定义的 jQuery 按钮单击事件:

在角度控制器中:

        // Note that I can even pass over the $scope to my CRUDManager's constructor.
        var crudManager = new CRUDManager($scope, contextData, opMode);

        crudManager.initialize()
            .then(() => {
                crudManager.dataBind();
                $scope.crudManager = crudManager;
                $scope.$apply();
            })
            .catch(error => {
                alert(error);
            });

在控制器外部的 jQuery Save 按钮单击事件中:

    $(document).on("click", "#ElementWithNgControllerDefined #btnSave", function () {
        var ngScope = angular.element($("#ElementWithNgControllerDefined")).scope();
        var crudManager = ngScope.crudManager;
        crudManager.saveData()
            .then(finalData => {
               alert("Successfully saved!");
            })
            .catch(error => {
               alert("Failed to save.");
            });
    });

当您的 jQuery 事件需要放置在控制器之外以防止它触发两次时,这尤其重要和有用。

于 2020-08-19T08:22:34.637 回答