来自 js 函数外部的 AngularJS 访问范围

我想看看是否有一种简单的方法可以通过外部 javascript 函数访问控制器的内部作用域(与目标控制器完全无关)

我在其他几个问题上看到

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

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

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

我现在正在经历从普通 JS 到角度的转变。我试图实现这一点的主要原因是尽可能保持我的原始库代码的完整性; 省去了我向控制器添加每个函数的需要。

对于如何实现这一目标有什么想法吗? 欢迎对上述小提琴的评论。

178821 次浏览

如果希望在 angularjs 控件之外对范围值进行任何更改,比如 jquery/javascript 事件处理程序,则需要使用 $范围 $运用()

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

演示: 小提琴

我已经有一段时间没有发布这个问题了,但是考虑到这个问题仍然得到的观点,这里有一个我在过去几个月中想到的解决方案:

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

上面的代码基本上创建了一个名为 safeApply的函数,它调用 $apply函数(如 Arun 的回答所述) ,当且仅当前 没有通过处于 $digest阶段时。另一方面,如果角度 正在消化的东西,它将只是执行的功能,因为这将是足够的信号,角度作出改变。

当 AngularJs 目前处于 $digest阶段时,在尝试使用 $apply函数时会出现许多错误。上面的 safeApply代码是防止此类错误的安全包装器。

(注意: 为了方便起见,我个人喜欢插入 safeApply作为 $rootScope的函数)

例如:

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

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

我们可以加载后叫它

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");
});
}

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

function change() {
var scope = angular.element(document.querySelector('#outside')).scope();
scope.$apply(function(){
scope.msg = 'Superhero';
})
}

接受的答案是好的。我想看看在 ng-repeat的背景下,角度范围会发生什么。事情是这样的,Angular 会为每个重复的项目创建一个子范围。当调用原始 $scope上定义的方法时,该方法保留其原始值(由于 javascript 闭包)。但是,this引用调用范围/对象。只要你清楚什么时候 $scopethis是相同的,什么时候它们是不同的,这样就可以很好地解决问题。嗯

下面的小提琴演示了这种差异: https://jsfiddle.net/creitzel/oxsxjcyc/

另一种方法是:

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';
})
<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);
});

这里有一个可重用的解决方案: 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';
});


};

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

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

我是这么用的:

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

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

你也可以试试:

function change() {
var scope = angular.element( document.getElementById('outer') ).scope();
scope.$apply(function(){
scope.msg = 'Superhero';
})
}

我们需要使用内置在函数 $申请中的角 J 来访问范围变量或控制器函数之外的函数。

这可以通过两种方式实现:

方法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 控制器的 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>

这就是我在 Angular 控制器中初始化的 CRUDManager class,它后来传递给 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 事件需要放置 在控制器之外以防止它从 开火两次发生时,这一点尤其重要和有用。