2014-11-25 57 views
22

對於局部視圖,我想要做一些JavaScript工作,我通常會使用$(document).ready(function() {...})(例如,將venet監聽器綁定到元素。我知道這不適用於AngularJS和部分視圖加載到「根」視圖。

因此,我向監聽$viewContentLoaded事件的控制器添加了一個監聽器。偵聽器的函數被調用,所以事件被觸發,但在我看來,好像它是在部分視圖呈現之前。當我在偵聽器函數中設置斷點並使用螢火蟲進行調試時,也沒有看到這些元素,函數中的jquery選擇也沒有找到部分視圖的元素。

這是控制器的樣子:

angular.module('docinvoiceClientAngularjsApp') 
    .controller('LoginController', function ($scope, $rootScope) { 

$scope.$on('$viewContentLoaded', function(event) { 
    console.log("content loaded"); 
    console.log($("#loginForm")); // breakpoint here 
}); 

[...] 

我想,我做錯了什麼,因爲必須是計算器上的更多內容,如果這是一個常見的錯誤。

由於我使用UI路由器UI視圖,我會給你的路由文件的摘錄:

angular 
    .module('docinvoiceClientAngularjsApp', [ 
    'ui.router', 
    'ngAnimate', 
    'ngCookies', 
    'ngResource', 
    'ngMessages', 
    'ngRoute', 
    'ngSanitize', 
    'ngTouch' 
    ]) 
.config(function ($routeProvider, $stateProvider) { 
    $stateProvider 
    .state('login', { 
     url: '/', 
     templateUrl: 'components/login/loginView.html', 
     controller: 'LoginController' 
    }) 
    .run(['$state', function ($state) { 
     $state.transitionTo('login'); 
    }]) 

[...] 

任何幫助表示讚賞。感謝和親切的問候

更新1:我扯下了錯誤下面的這個用例:該loginView.html如下所示:

<div id="loginContainer" style="width: 300px"> 
    <form id="loginForm" ng-submit="login(credentials)" ng-if="session.token == undefined"> 

[...] 

當我從div標籤取下ng-if ,它按預期工作。事件在DOM呈現後觸發,因此jQuery找到元素。如果ng-if連接到div標籤,則行爲如第一次描述。

UPDATE 2:按照承諾,我添加了一個工作演示,顯示添加ng-if指令時的不同行爲。任何人都可以指出正確的方向嗎?不要拘泥於登錄表單,因爲還有更多的用例,我想根據某些表達式刪除視圖的某些部分,並在部分視圖準備好後執行一些JavaScript。

你可以在這裏找到了工作演示:Demo

+0

您可以爲您創建一個指示DOM的東西。 – dfsq 2014-11-25 14:55:15

+1

我已經根據你的代碼創建了一個[工作演示](http://codepen.io/anon/pen/gbpmQy),它工作正常。下一次,請嘗試自己提供演示。 – hon2a 2014-11-25 15:18:55

+0

非常感謝您的演示。我已經更新了描述,因爲我發現ng-if會導致不同的行爲。你有一個想法,爲什麼它的行爲不同?該表達式被評估爲「真」,因爲我可以看到登錄表單,只是片刻太遲;) – Florian 2014-11-25 15:50:43

回答

39

這與角消化週期,它是關於如何角作品引擎蓋下,數據綁定等方面有很大的教程說明這一點。

解決您的問題,使用$超時,就會使代碼執行在下一個週期,whem的NG-如果已經解析:

app.controller('LoginController', function ($scope, $timeout) { 
    $scope.$on('$viewContentLoaded', function(event) { 
     $timeout(function() { 
     $scope.formData.value = document.getElementById("loginForm").id; 
     },0); 
    }); 
}); 

固定演示在這裏:http://codepen.io/anon/pen/JoYPdv

但我強烈建議你使用指令做任何DOM操作,控制器不是這樣的。 這是如何做到這一點的一個例子: Easy dom manipulation in AngularJS - click a button, then set focus to an input element

+0

我會認爲這是最有價值的答案,因爲它提供了一個可能的解決方案和提示來查找有關摘要循環的更多信息,儘管我現在正在使用指令。 – Florian 2014-12-01 11:12:30

+0

很好解釋!我能夠通過使用上面的代碼塊來集成App.js和AngularJS,並且還可以理解超時複雜的細節。 – Nirus 2015-05-08 11:42:17

+6

這種方法的問題是,在ui-router $ viewContentLoaded爲每個視圖觸發。 如果您在單個頁面中有很多視圖,您的代碼將執行多次。有沒有辦法讓它只執行一次ALL視圖加載? – Hades 2015-06-22 14:51:47

0

這是一個答案冥王星有點遲,但可能會幫助別人。我設置了一個服務,我稍後可以從控制器或指令中調用。

'use strict'; 
 

 
app.factory('viewContentLoaded', function($q, $rootScope, $timeout) { 
 
    var viewContentLoaded = $q.defer(), 
 
     
 
     foo = function() { 
 
      $timeout(function() { 
 
       viewContentLoaded.resolve(); 
 
       // Get all entries 
 
      }, 100);//Timeout 
 
     }, 
 

 
     checkViewContenLoadedListner = $rootScope.$on('$viewContentLoaded', foo);//Rootscope 
 

 
    return { 
 
     getLoaded: function() {  
 
      return viewContentLoaded.promise; 
 
     }, 
 
     removeViewContenListner: function() { 
 
      //Remove event listern on $viewContentLoaded no $off so call it will unsubscribe it 
 
      //$rootScope.$off('$viewContentLoaded', foo);//Rootscope 
 
      //Don't forget to unsubscribe later 
 
      checkViewContenLoadedListner(); 
 
     } 
 

 
    }; 
 
});

在控制器或指令包括viewContentLoaded,並呼籲與承諾get函數。不要忘記將應用程序更改爲您的應用程序名稱,幷包含要加載的服務文件。

viewContentLoaded.getLoaded().then(function(){ 
 
    //Remove Listner when done 
 
    viewContentLoaded.removeViewContenListner(); 
 
    //Your code to run  
 

 
}, function(reason) { 
 
    //$log.error(reason); 
 
});

1

我已經解決了與指令的幫助下這個問題。一個direcitve添加到您的元素(如<div my-dir></div>),並做操作到相應的指令元素如下,

app.directive('myDir', function() { 
    return { 
     restrict: 'A', 
     link: function (scope, element) { 
      // Do manipulations here with the help of element parameter 
     } 
    }; 
}); 

我也曾嘗試狀態提供事件,如$stateChangeSuccess$viewContentLoaded但未能解決問題。因爲在這些事件被解僱之後,在DOM上渲染需要時間。

所以,我們可以按照這種方式賦予完美的效果和正確的方式角JS實現:)

相關問題