js関数の外部からのAngularJSアクセススコープ


131

外部のJavaScript関数を介してコントローラーの内部スコープにアクセスする簡単な方法があるかどうかを確認しようとしています(完全にターゲットコントローラーとは無関係です)。

私はここで他のいくつかの質問を見てきました

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

DOM要素からスコープを取得しますが、現在のところ、適切な結果が得られていません。

ここにjsfiddleがあります:http ://jsfiddle.net/sXkjc/5/

私は現在、プレーンなJSからAngularへの移行を行っています。私がこれを達成しようとしている主な理由は、元のライブラリコードをできるだけそのままにしておくためです。コントローラに各機能を追加する必要がなくなります。

これを達成する方法を教えてください。上記のフィドルについてのコメントも歓迎します。


使用.scope()するドキュメントによると、参考までにデバッグデータを有効にする必要がありますが、本番環境でデバッグデータを使用すること、速度上の理由からお勧めできません。以下の解決策は中心に展開しているようですscope()
rtpHarry

@rtpHarryは正しいです。scope()の使用を必要とする以下の回答は非推奨です。ここに私の答えを参照してくださいstackoverflow.com/a/34078750/319302
Cagatayカラン

回答:


223

jquery / javascriptイベントハンドラーのようにangularjsのコントロールの外側からスコープ値に変更を加える場合は、$ scope。$ apply()を使用する必要があります。

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

デモ:フィドル


2
@ dk123 angular.element("#scope")は機能していませんangular.element($("#scope"))が、機能していますが、jqueryも必要です
Arun P Johny

1
久しぶりに知っていますが、これについて答えてくれる人がいるといいのですが... var scope = angular.element($( "#outer"))。scope(); change関数内で宣言する必要がありますか?グローバルスペースに移動した場合、それは問題ありませんか?
Marc M.

1
@MarcM。Angularのスコープレクリエーションに関係していると思います。change関数を使用しているときには、グローバル変数が指していた以前のスコープは存在しない可能性があります(再作成のため)。
dk123

1
angular.element($( "div [ng-controller = 'myCtrl']"))。scope(); div要素に#outerを追加するよりも優れていると思います
wyverny 2016年

1
実行すると、scope()は未定義になります。$ compileProvider.debugInfoEnabled(false); 角度で。それでは、debuginfoEnabled falseでどのように機能させることができますか?
Agnosco 2016年

26

私がこの質問を投稿してからしばらく経ちましたが、これがまだ得られていると思われる見解を考えると、ここ数か月間に私が思いついた別の解決策があります:

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

上記のコードは基本的に、Angularだけがステージを通過しいない場合に、(Arunの回答で述べたように)関数safeApplyを呼び出すという$apply関数を作成します。一方、Angular が現在物事を消化している場合は、Angularに変更を通知するのに十分であるため、関数をそのまま実行します。$digest

$applyAngularJsが現在その$digest段階にあるときに関数を使用しようとすると、多数のエラーが発生します。上記のsafeApplyコードは、このようなエラーを防ぐ安全なラッパーです。

(注:個人的にsafeApply$rootScope、便宜上、の機能としてのんびりしたいです)

例:

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

デモ:http : //jsfiddle.net/sXkjc/227/


1
safeApply関数が機能するのはなぜですか?「Angularが$ applyまたは$ digestステージにある場合は関数を単独で実行し、そうでない場合は$ apply()を使用して関数を適用する」というように見えますが、関数を単独で実行する場合は、 ..モデルをどのように更新するのですか?私が知らないことが起こっていない限り、それは好ましい行動ではないようです。Angularのいくつかのメカニズムは、それに直接起こったかもしれない変更のために$ scopeに投票しますか?
trusktr 2014年

さらに、これらの状態から保護する必要がある場合は、$ apply()メソッドのバグを修正する必要があると考えます。
trusktr 2014年

@trusktr私が理解しているところによると、関数がモデルを変更する場合、関数の実行は通常、angularによってキャッチされるため、angularは次のダイジェスト段階でそれらを更新します。
dk123 2014年

@trusktr私は、通常の$ apply()がセーフガードなしで適用できる場合、それ以上のことはないことに同意します。本質的に、safeApplyの唯一の目的は、$ apply()エラーから保護することです。これが報告された問題で現在修正されているのか、それともまだ進行中の問題なのかはわかりません。
dk123 2014年

1
私がつまずいたからといって:github.com/angular/angular.js/wiki/When-to-use-$scope.$apply()。(!$範囲$$相)あなたがあれば$スコープを行っている_if $(適用)を使用すると、コールstack._に高く十分ではないからだ。
scheffield

17

これを行う別の方法は次のとおりです。

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

1
このコメントがこれに対する最良の回答ではない理由はまだわかりません。欲求不満と怒りで数日間インターネットを掘り下げた後、最後にこれが私の問題を解決したものです。@Charlestonありがとうございます。あなたは素晴らしいです、先生!
Rajkumar

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

8

この質問をしてから久しぶりですが、jqueryを必要としない回答を次に示します。

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

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

};

2

あなたも試すことができます:

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

@ dk123これもJQueryを必要としません。
シャルマを磨く2017年

1

受け入れられた答えは素晴らしいです。Angularスコープに何が起こるかをのコンテキストで確認したいと思いましたng-repeat。実際のところ、Angularは繰り返されるアイテムごとにサブスコープを作成します。元の$scopeで定義されたメソッドを呼び出すと、(JavaScriptの閉鎖により)元の値が保持されます。ただし、はthis呼び出しスコープ/オブジェクトを参照します。これは、限り、あなたはときに明確だと、うまく働く$scopethis同じであり、彼らが異なる場合。hth

これが違いを示すフィドルです:https : //jsfiddle.net/creitzel/oxsxjcyc/


1

私は初心者なので、悪い習慣があれば申し訳ありません。選択した答えに基づいて、私はこの機能を実行しました:

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

私はそれをこのように使用しています:

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

ちなみに私の英語は申し訳ありません


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);
        });

0

コントローラー変数の外でスコープ変数または関数をアクセスするには、Angular Js組み込み関数$ applyを使用する必要があります。

これは2つの方法で実行できます。

| * | 方法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>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.