Подтвердить что ты не робот

Как изменить данные AngularJS вне рамок?

После нескольких часов разочаровывающих поисков я чувствую, что мне нужно представить свой вопрос здесь. Я заранее извиняюсь, если этот вопрос каким-то образом до ответа, но ни один из моих поисков не помог до сих пор. Итак, вот мой вопрос:

Мой код JavaScript создает объект, который модифицируется и контролируется AngularJS. В некоторых случаях (например, загрузка предыдущей настройки объекта) я хочу изменить свойства этого объекта извне области. Проблема в том, что входы не меняются...

Вот пример того, как я хочу выполнить эти изменения:


Код HTML:

<div ng-app="myApp" ng-controller="FirstCtrl">
<input type="number" ng-model="data.age">
<h1>{{data.age}}</h1>

<input type="button" value="Change to 20" ng-model="data" onclick="change()">

Код JavaScript:

var person = {
    age: 16
};

// Create module
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
    return person;
});

function FirstCtrl($scope, Data) {
    $scope.data = Data;
}

function change() {
    person.age = 20;
}

Когда я сейчас нажимаю кнопку "Изменить на 20", ничего не происходит. Как изменить возраст человека из функции change?

4b9b3361

Ответ 1

⚠️ Предупреждение: Этот ответ старый, не отражает лучших практик и может быть несовместим с более новыми версиями Angular.

Ответ MaxPRafferty верный - использование функции в области часто является лучшим способом сделать это, но есть и другой вариант. Вы можете использовать метод angular.element(...).scope() для доступа к области Angular из несвязанного JavaScript. Выберите область верхнего уровня для приложения, настроив на него элемент с указанным атрибутом ng-app, с чем-то вроде обработчика кликов:

function change() {
    var appElement = document.querySelector('[ng-app=myApp]');
    var $scope = angular.element(appElement).scope();
    $scope.$apply(function() {
        $scope.data.age = 20;
    });
}

Попробуйте в этой скрипте.

Shaun только что указал, что Angular обрабатывает только "часы" или "часы", привязки "во время вызова $digest(). Если вы просто изменяете свойства $scope напрямую, изменения могут не отображаться немедленно, и вы можете получить ошибки.

Чтобы вызвать это, вы можете вызвать $scope.$apply(), который будет проверять наличие грязных областей и правильно обновлять что-либо связанное. Передача функции, которая выполняет работу внутри $scope.$apply, позволит Angular также поймать любые исключения. Это поведение объясняется в документации для области.

Ответ 2

Ответ Джереми действительно хорош, хотя теперь Angular изменился и больше не будет работать, если вы не добавите эту строку кода:

$scope = $scope.$$childHead;

Итак, измененная функция должна выглядеть так:

function change() {
    var appElement = document.querySelector('[ng-app=myApp]');
    var $scope = angular.element(appElement).scope();
    $scope = $scope.$$childHead; // add this and it will work
    $scope.$apply(function() {
        $scope.data.age = 20;
    });
}

Ответ 3

http://jsfiddle.net/MaxPRafferty/GS6Qk/

Вы хотите настроить атрибут ng-click на функцию в своей области, как показано ниже:

var person = {
    age: 16
};

// Create module
var myApp = angular.module('myApp', []);
myApp.factory('Data', function() {
    return person;
});

function FirstCtrl($scope, Data) {
    $scope.data = Data;
    $scope.update = function(){
        $scope.data.age = 20;
    }
}

Ответ 4

Используя отличный ответ Джереми Бэнкса, сделанный в одной строке, хотя я ссылаюсь на контроллер и приложение:

angular.element('[ng-controller=myController]').scope().$apply(function(x){ x.foo = "bar"; });

Ответ 5

Просто используйте короткий $timeout

var whatever = 'xyz';
$timeout(function(){
    $scope.yourModel.yourValue = whatever;
}, 0);

и все готово.

Я пробовал все эти $apply hacks со всего www раньше, и все они не работали. Но этот $timeout работает всегда как charme и в каждом случае. Все, что вам нужно, это ссылка на ваш $scope и $timeout.

Wy и как это работает:

// Imagine an angular buildin-function
angular.$queue = function(fn){
    $timeout(fn, 0);
}

Он работает в основном как очередь. Но имейте в виду, что это асинхронно.

Ответ 6

С методом $render метод вызывается директивой ng-model, когда значение было изменено вне директивы. Получите новое значение, прочитав свойство $viewValue. Посмотрите: https://jsfiddle.net/cesar_ade/g5ybs6ne/

ctrl.$render=function(){
    setSelected(ctrl.$viewValue || 'Not Sure');
}