web-dev-qa-db-fra.com

Portée d'accès AngularJS depuis la fonction js extérieure

J'essaie de voir s'il existe un moyen simple d'accéder à la portée interne d'un contrôleur via une fonction javascript externe (totalement inutile pour le contrôleur cible).

J'ai vu sur quelques autres questions ici que

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

récupérerait la portée d'un élément DOM, mais mes tentatives ne donnent actuellement aucun résultat correct.

Voici le jsfiddle: http://jsfiddle.net/sXkjc/5/

Je suis actuellement en train de traverser une transition de JS simple à Angular. La principale raison pour laquelle j'essaie d'y parvenir est de garder mon code de bibliothèque d'origine intact autant que possible. Cela évite de devoir ajouter chaque fonction au contrôleur.

Des idées sur la façon dont je pourrais y arriver? Les commentaires sur le violon ci-dessus sont également les bienvenus.

129
dk123

Vous devez utiliser $ scope. $ Apply () si vous souhaitez apporter des modifications à une valeur de portée en dehors du contrôle de angularjs, comme un gestionnaire d'événements jquery/javascript.

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

Démo: Violon

221
Arun P Johny

Cela fait longtemps que je n'ai pas posté cette question, mais compte tenu des points de vue qui semblent partagés, voici une autre solution à laquelle je suis parvenue au cours de ces derniers mois:

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

Le code ci-dessus crée essentiellement une fonction appelée safeApply qui appelle la fonction $apply (comme indiqué dans la réponse de Arun) si et seulement Angular actuellement isn pas passer le stade $digest. Par contre, si Angular digère actuellement des choses, il ne fera qu'exécuter la fonction telle quelle, car ce sera Assez pour signaler à Angular pour effectuer les modifications.

De nombreuses erreurs se produisent lorsque vous essayez d'utiliser la fonction $apply alors qu'AngularJs est actuellement dans sa phase $digest. Le code safeApply ci-dessus est un wrapper sûr pour éviter de telles erreurs.

(Remarque: j'aime personnellement ajouter safeApply en fonction de $rootScope à des fins pratiques)

Exemple:

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

Démo: http://jsfiddle.net/sXkjc/227/

26
dk123

ne autre façon de faire est:

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

nous pouvons l'appeler après chargé

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

Cela fait longtemps que je n'ai pas posé cette question, mais voici une réponse qui n'exige pas jQuery:

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

Voici une solution réutilisable: 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';
    });

};
3
flobar

Vous pouvez aussi essayer:

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

Je suis débutant, alors désolé si c'est une mauvaise pratique. Sur la base de la réponse choisie, j'ai effectué cette fonction:

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

Je l'utilise de cette façon:

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

Au fait, désolé pour mon anglais

1
MrQwerty

La réponse acceptée est géniale. Je voulais regarder ce qui arrive à la portée Angular dans le contexte de ng-repeat. Le problème est que Angular créera une sous-portée pour chaque élément répété. Lors de l'appel d'une méthode définie sur l'original $scope, celle-ci conserve sa valeur d'origine (en raison de la fermeture de javascript). Cependant, la this fait référence à la portée/à l'objet appelant. Cela fonctionne bien, tant que vous savez clairement quand $scope et this sont identiques et quand ils sont différents. hth

Voici un violon qui illustre la différence: https://jsfiddle.net/creitzel/oxsxjcyc/

1
Charlie

Nous devons utiliser la fonction intégrée Angular Js $ apply pour valider des variables de portée ou des fonctions extérieures à la fonction de contrôleur.

Ceci peut être fait de deux façons :

| * | Méthode 1: Utiliser 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>

| * | Méthode 2: Utilisation de init of 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>
0
Sujay U N
<input type="text" class="form-control timepicker2" ng-model='programRow.StationAuxiliaryTime.ST88' />

accéder à la valeur de la portée

supposons que programRow.StationAuxiliaryTime soit un tableau d'objets

 $('.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);
        });
0
Sreeraj