我试图通过外部javascript函数(与目标控制器完全无关)来查看是否有一种简单的方法来访问控制器的内部范围
我在这里看到了其他几个问题
angular.element("#scope").scope();
会从DOM元素中检索范围,但我的尝试目前没有产生正确的结果。
这是jsfiddle:http://jsfiddle.net/sXkjc/5/
我目前正在经历从普通JS到Angular的过渡。我试图实现这一目标的主要原因是尽可能保持原始库代码的完整性;无需我将每个功能添加到控制器。
关于如何实现这一目标的任何想法?对上述小提琴的评论也很受欢迎。
答案 0 :(得分:221)
如果要从angularjs控件之外对范围值进行任何更改(如jquery / javascript事件处理程序),则需要使用$scope.$apply()。
function change() {
alert("a");
var scope = angular.element($("#outer")).scope();
scope.$apply(function(){
scope.msg = 'Superhero';
})
}
演示:Fiddle
答案 1 :(得分: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发出信号以进行更改。
当AngularJs当前处于$apply
阶段时,尝试使用$digest
函数时会出现许多错误。上面的safeApply
代码是一个安全的包装器,可以防止出现此类错误。
(注意:出于方便的目的,我个人喜欢将safeApply
作为$rootScope
的函数进行查看)
示例:
function change() {
alert("a");
var scope = angular.element($("#outer")).scope();
scope.safeApply(function(){
scope.msg = 'Superhero';
})
}
答案 2 :(得分:15)
另一种方法是:
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';
})
答案 3 :(得分: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");
});
}
答案 4 :(得分:8)
自从我提出这个问题已经有很长一段时间了,但是这里的答案不需要jquery:
function change() {
var scope = angular.element(document.querySelector('#outside')).scope();
scope.$apply(function(){
scope.msg = 'Superhero';
})
}
答案 5 :(得分: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';
});
};
答案 6 :(得分:2)
您也可以尝试:
function change() {
var scope = angular.element( document.getElementById('outer') ).scope();
scope.$apply(function(){
scope.msg = 'Superhero';
})
}
答案 7 :(得分:1)
接受的答案很棒。我想看一下ng-repeat
上下文中Angular范围会发生什么。问题是,Angular将为每个重复项创建一个子范围。调用原始$scope
上定义的方法时,会保留其原始值(由于javascript闭包)。但是,this
引用调用范围/对象。只要您清楚$scope
和this
何时相同以及何时不同,这一点就可以了。 HTH
这是一个说明差异的小提琴:https://jsfiddle.net/creitzel/oxsxjcyc/
答案 8 :(得分:1)
我是新手,很抱歉,如果这是一个不好的做法。根据所选答案,我做了这个功能:
function x_apply(selector, variable, value) {
var scope = angular.element( $(selector) ).scope();
scope.$apply(function(){
scope[variable] = value;
});
}
我这样使用它:
x_apply('#fileuploader', 'thereisfiles', true);
顺便说一句,抱歉我的英文
答案 9 :(得分: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);
});
答案 10 :(得分:0)
我们需要使用内置函数 $ apply 的Angular 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-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>
答案 11 :(得分:0)
这就是我在Angular控制器中初始化CRUDManager class
的方式,后来将其传递给在控制器外部定义的jQuery按钮单击事件:
在Angular Controller中:
// 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事件放置在控制器外部以防止其触发两次时,这特别重要且有用。