Доступ к AngularJS извне функции js
Я пытаюсь увидеть, есть ли простой способ доступа к внутренней области видимости контроллера через внешнюю функцию javascript (совершенно не относящуюся к целевому контроллеру)
Я видел на пару других вопросов здесь, что
angular.element("#scope").scope();
будет получать область видимости от элемента DOM, но мои попытки в настоящее время не дают должных результатов.
Вот jsfiddle: http://jsfiddle.net/sXkjc/5/
В настоящее время я прохожу переход от простого JS к Angular. Основная причина, по которой я пытаюсь это сделать, - сохранить исходный код библиотеки как можно более неповрежденным; избавляя меня от необходимости добавлять каждую функцию в контроллер.
Любые идеи о том, как я мог бы добиться этого? Комментарии к вышеупомянутой скрипке также приветствуются.
11 ответов
Вам нужно использовать $scope.$ Apply(), если вы хотите внести какие-либо изменения в значение области из-за пределов контроля 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
функция (как указано в ответе Аруна), если и только 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';
})
}
Еще один способ сделать это:
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';
})
Мы можем назвать это после загрузки
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';
})
}
Вот многоразовое решение: 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 change() {
var scope = angular.element( document.getElementById('outer') ).scope();
scope.$apply(function(){
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);
Кстати, извините за мой английский
Принятый ответ великолепен. Я хотел посмотреть на то, что происходит с угловой областью в контексте ng-repeat
, Дело в том, что Angular создаст подцел для каждого повторяющегося элемента. При вызове метода, определенного в оригинале $scope
, который сохраняет свое первоначальное значение (из-за закрытия JavaScript). Тем не менее this
ссылается на вызывающую область / объект. Это хорошо работает, пока вы ясно, когда $scope
а также this
одинаковы и когда они разные. НТН
Вот скрипка, которая иллюстрирует разницу: https://jsfiddle.net/creitzel/oxsxjcyc/
Так я поступил со своим CRUDManager class
инициализируется в контроллере Angular, который позже передается событию нажатия кнопки 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 Сохранить событие нажатия кнопки вне контроллера:
$(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 необходимо разместить ВНЕ КОНТРОЛЛЕРА, чтобы предотвратить его повторное срабатывание.
<input type="text" class="form-control timepicker2" ng-model='programRow.StationAuxiliaryTime.ST88' />
доступ к значению области
Предположим, что programRow.StationAuxiliTime является массивом объектов
$('.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);
});
Нам нужно использовать встроенную функцию Angular J $apply для доступа к переменным области видимости или функциям вне функции контроллера.
Это можно сделать двумя способами:
| * | Способ 1: использование идентификатора:
<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: использование init ng-controller:
<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>