How to change AngularJS data outside the scope?

前端 未结 6 528
梦谈多话
梦谈多话 2020-12-05 04:33

After hours of frustrating searches I feel I need to submit my question here. I apologize in advance if this question is somehow answered before but none of my searches has

相关标签:
6条回答
  • 2020-12-05 04:35

    ⚠️ Warning: This answer is old, does not reflect best practices, and may not be compatible with newer versions of Angular.

    MaxPRafferty's answer is correct - using a function in the scope is often the nicer way to do this - but there is another option. You can use the angular.element(...).scope() method to access an Angular scope from unrelated JavaScript. Select the top-level scope for the app by targeting the element that has the ng-app attribute specified, with something like in your click handler:

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

    Try it out in this Fiddle.

    Shaun just pointed out that Angular will only process any "watches" or "bindings" during a $digest() call. If you just modify the properties of the $scope directly, the changes may not be reflected immediately and you may gets bugs.

    To trigger this you can call $scope.$apply() which will check for dirty scopes and update anything bound correctly. Passing a function that does the work inside $scope.$apply will allow Angular to catch any exceptions as well. This behaviour is explained in the documentation for Scope.

    0 讨论(0)
  • 2020-12-05 04:38

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

    You want set your ng-click attribute to a function in your scope, as follows:

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-05 04:44

    Using Jeremy Banks' perfect answer, done in one line, though I'm referencing the controller vs the app:

    angular.element('[ng-controller=myController]').scope().$apply(function(x){ x.foo = "bar"; });
    
    0 讨论(0)
  • 2020-12-05 04:46

    With $render method is called by the ng-model directive when the value has been modified outside the directive. Get new value by reading the $viewValue property. Look: https://jsfiddle.net/cesar_ade/g5ybs6ne/

    ctrl.$render=function(){
        setSelected(ctrl.$viewValue || 'Not Sure');
    }
    
    0 讨论(0)
  • 2020-12-05 04:51

    Jeremy's answer is really good, though now Angular has changed, and will no longer work, unless you add this line of code:

    $scope = $scope.$$childHead;
    

    So, the changed function should look like this

    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;
        });
    }
    
    0 讨论(0)
  • 2020-12-05 04:52

    Simply use a short $timeout

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

    and you are done.

    I tried all those $apply hacks from around the www before and they all didn't work. But this $timeout works always like a charme and in every case. All you need is a reference of your $scope and $timeout.

    Wy and how it works:

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

    It works basically like a queue. But be aware that it is async.

    0 讨论(0)
提交回复
热议问题