web-dev-qa-db-ja.com

文書の角度コントローラーで機能を実行する方法

私は自分の角度コントローラ内に機能を持っています、私はこの機能をドキュメントの準備ができて実行したいのですが、私はDOMが作成されると角度がそれを実行することに気づきました。

 function myController($scope)
 {
     $scope.init = function()
     {
        // I'd like to run this on document ready
     }

     $scope.init(); // doesn't work, loads my init before the page has completely loaded
 }

誰もが私がこれに取り組むことができる方法を知っていますか?

244
foreyez

ドキュメントの準備ができたときにコールバックを添付するためにangular.element(document).ready()メソッドを使うことができます。以下のようにコールバックをコントローラにアタッチするだけです。

angular.module('MyApp', [])

.controller('MyCtrl', [function() {
    angular.element(document).ready(function () {
        document.getElementById('msg').innerHTML = 'Hello';
    });
}]);

http://jsfiddle.net/jgentes/stwyvq38/1/ /

435
Will

この記事を参照してください ページの読み込み時に角度コントローラ機能を実行する方法?
高速検索の場合:

// register controller in html
<div data-ng-controller="myCtrl" data-ng-init="init()"></div>

// in controller
$scope.init = function () {
    // check if there is query in url
    // and fire search in case its value is not empty
};

こうすれば、文書の準備ができるまで待つ必要はありません。

28
vinesh

AngularはDOMContentLoadedイベントの際、またはその時点でdocument.readyStateが 'complete'に設定されている場合、angular.jsスクリプトが評価されると自動的に初期化されます。この時点でAngularは、アプリケーションルートを指定するng-appディレクティブを探します。

https://docs.angularjs.org/guide/bootstrap

これは、DOMの準備ができた後にコントローラーコードが実行されることを意味します。

したがって、それは単に$scope.init()です。

22
Will M

Angularには、関数の実行を開始するためのいくつかの時点があります。あなたがjQueryのような何かを探しているなら

$(document).ready();

あなたは非常に有用であると角度でこのアナログを見つけるかもしれません:

$scope.$watch('$viewContentLoaded', function(){
    //do something
});

これはDOM要素を操作したいときに役立ちます。すべてのte要素がロードされた後にのみ実行を開始します。

UPD:CSSのプロパティを変更したい場合は、上記の説明が役に立ちます。ただし、幅、高さなどの要素のプロパティを測定したいときに、うまく動作しないことがあります。

$scope.$watch('$viewContentLoaded', 
    function() { 
        $timeout(function() {
            //do something
        },0);    
});
17
Alex Link

ビューがロードされた後、ビュー内の特定のサードパーティコンポーネントがロードされ、初期化され、それ自身への参照を$ scopeに配置した後にも、同様にコントローラー関数を実行する必要がありました。私にとってうまくいったのは、このscopeプロパティの監視を設定し、それが初期化された後にだけ私の関数を起動することでした。

// $scope.myGrid property will be created by the grid itself
// The grid will have a loadedRows property once initialized

$scope.$watch('myGrid', function(newValue, oldValue) {
    if (newValue && newValue.loadedRows && !oldValue) {
        initializeAllTheGridThings();
    }
});

ウォッチャーは未定義の値で数回呼び出されます。グリッドが作成され、そして期待されたプロパティを持つとき、初期化関数が安全に呼び出されます。ウォッチャーが未定義のnewValueを指定して最初に呼び出されたときには、oldValueは未定義のままです。

2
MikeyM

答え

$scope.$watch('$viewContentLoaded', 
    function() { 
        $timeout(function() {
            //do something
        },0);    
});

私がテストしたほとんどのシナリオで機能するのは唯一のものです。テンプレートからHTMLを構築する4つのコンポーネントを含むサンプルページでは、イベントの順序は次のとおりです。

$document ready
$onInit
$postLink
(and these 3 were repeated 3 more times in the same order for the other 3 components)
$viewContentLoaded (repeated 3 more times)
$timeout execution (repeated 3 more times)

そのため、$ document.ready()は、角度付きで構築されているDOMの準備が整っていないため、ほとんどの場合役に立ちません。

しかし、さらに興味深いことに、$ viewContentLoadedが発生した後でも、関心のある要素はまだ見つかりませんでした。

$ timeoutが実行された後に初めて発見されました。 $ timeoutが0の値であっても、実行前に約200ミリ秒が経過したことに注意してください。おそらく、このスレッドはしばらくの間保留されていたのでしょう。最初の$ document.ready()から最後の$ timeout実行までの合計時間は約500ミリ秒でした。

コンポーネントの値が設定され、その後$ timeoutの後半にtext()値が変更されたという特別なケースでは、$ timeoutの値が機能するまで増やす必要がありました($ timeout中に要素が見つかったとしても) )十分な時間が経過するまで、サードパーティコンポーネント内で何か非同期がテキストよりも値が優先されるようになりました。他の可能性は$ scope。$ evalAsyncですが、試みられませんでした。

私はまだDOMが完全に落ち着いていて、すべてのケースがうまくいくように操作できることを私に伝えるその1つのイベントを探しています。これまでのところ、任意のタイムアウト値が必要です。これはせいぜいこれが遅いブラウザでは動作しないかもしれないクラッジであることを意味します。 liveQueryやpublish/subscribeのようなJQueryのオプションを試してみたことはありませんが、確かに純粋ではありません。

1
Wray Smallwood

getElementById call returns nullのようなものになっているのであれば、それはおそらく関数が実行されているためですが、IDはDOMに読み込む時間がありませんでした。

ウィルの答えを(上に向かって)遅れて使ってみてください。例:

angular.module('MyApp', [])

.controller('MyCtrl', [function() {
    $scope.sleep = (time) => {
        return new Promise((resolve) => setTimeout(resolve, time));
    };
    angular.element(document).ready(function () {
        $scope.sleep(500).then(() => {        
            //code to run here after the delay
        });
    });
}]);
1
Mr. Green

これが、coffeescriptを使用した外部コントローラ内での私の試みです。それはかなりうまくいきます。 settings.screen.xs | sm | md | lgは、アプリに含まれている、まだ説明されていないファイルで定義された静的な値です。値は、同名のメディアクエリサイズに対するBootstrap 3の公式ブレークポイントに基づいています。

xs = settings.screen.xs // 480
sm = settings.screen.sm // 768
md = settings.screen.md // 992
lg = settings.screen.lg // 1200

doMediaQuery = () ->

    w = angular.element($window).width()

    $scope.xs = w < sm
    $scope.sm = w >= sm and w < md
    $scope.md = w >= md and w < lg
    $scope.lg = w >= lg
    $scope.media =  if $scope.xs 
                        "xs" 
                    else if $scope.sm
                        "sm"
                    else if $scope.md 
                        "md"
                    else 
                        "lg"

$document.ready () -> doMediaQuery()
angular.element($window).bind 'resize', () -> doMediaQuery()
1
akutz
$scope.$on('$ViewData', function(event) {
//Your code.
});
0
Shreyansh Kumar

https://docs.angularjs.org/api/ng/function/angular.element に記載されている角度のドキュメントで試してみませんか。

angular.element(コールバック)

これを私の$ onInit(){...}関数の中で使いました。

 var self = this;

 angular.element(function () {
        var target = document.getElementsByClassName('unitSortingModule');
        target[0].addEventListener("touchstart", self.touchHandler, false);
        ...
    });

これは私のために働きました。

0
Mahib