Làm cách nào để thực thi chức năng điều khiển AngularJS khi tải trang?


359

Hiện tại tôi có trang Angular.js cho phép tìm kiếm và hiển thị kết quả. Người dùng nhấp vào kết quả tìm kiếm, sau đó nhấp vào nút quay lại. Tôi muốn kết quả tìm kiếm được hiển thị lại nhưng tôi không thể tìm ra cách kích hoạt tìm kiếm để thực hiện. Đây là chi tiết:

  • Trang Angular.js của tôi là trang tìm kiếm, với trường tìm kiếm và nút tìm kiếm. Người dùng có thể nhập thủ công một truy vấn và nhấn nút và truy vấn ajax được kích hoạt và kết quả được hiển thị. Tôi cập nhật URL với cụm từ tìm kiếm. Đó là tất cả hoạt động tốt.
  • Người dùng nhấp vào kết quả tìm kiếm và được đưa đến một trang khác - cũng hoạt động tốt.
  • Người dùng nhấp vào nút quay lại và quay lại trang tìm kiếm góc cạnh của tôi và URL chính xác được hiển thị, bao gồm cả cụm từ tìm kiếm. Tất cả đều hoạt động tốt.
  • Tôi đã ràng buộc giá trị trường tìm kiếm với cụm từ tìm kiếm trong URL, vì vậy nó chứa cụm từ tìm kiếm dự kiến. Tất cả đều hoạt động tốt.

Làm cách nào để chức năng tìm kiếm thực hiện lại mà không cần người dùng phải nhấn "nút tìm kiếm"? Nếu đó là jquery thì tôi sẽ thực thi một hàm trong hàm document yet. Tôi không thể thấy tương đương Angular.js.


bạn đang sử dụng $routepProviderà Sử dụng nó để kết nối với dịch vụ trong ứng dụng của bạn cung cấp dữ liệu cho kết quả tìm kiếm. Đừng nghĩ theo document.readythuật ngữ như với jQuery. Thật khó để giúp đỡ nhiều mà không nắm bắt được cách bạn tìm kiếm hiện tại có dây
charlietfl 17/03/13

Câu trả lời:


430

Một mặt như @ Mark-Rajcok nói rằng bạn có thể thoát khỏi chức năng bên trong riêng tư:

// at the bottom of your controller
var init = function () {
   // check if there is query in url
   // and fire search in case its value is not empty
};
// and fire it after definition
init();

Ngoài ra, bạn có thể xem chỉ thị ng-init . Việc thực hiện sẽ giống như:

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

Nhưng hãy chú ý đến nó vì tài liệu góc cạnh ngụ ý (kể từ v1.2) KHÔNG được sử dụng ng-initcho điều đó. Tuy nhiên, imo nó phụ thuộc vào kiến ​​trúc của ứng dụng của bạn.

Tôi đã sử dụng ng-initkhi tôi muốn chuyển một giá trị từ back-end vào ứng dụng góc cạnh:

<div data-ng-controller="myCtrl" data-ng-init="init('%some_backend_value%')"></div>

6
@Duke, bạn không thể đặt nội dung của hàm init () ở dưới cùng của bộ điều khiển của bạn? Tức là tại sao bạn cần sử dụng ng-init và có hàm init ()? Khi người dùng nhấn nút quay lại, tôi giả sử bạn đang chuyển đổi chế độ xem, do đó myCtrlbộ điều khiển mới được tạo và thực thi.
Mark Rajcok 18/03/13

24
Trong khi giải pháp này hoạt động, tôi đã bỏ qua vì tài liệu ng-init khuyên chống lại điều này. Cụ thể, "Việc sử dụng ngInit thích hợp duy nhất cho các thuộc tính đặc biệt của ngRepeat, như đã thấy trong bản demo bên dưới. Bên cạnh trường hợp này, bạn nên sử dụng các bộ điều khiển thay vì ngInit để khởi tạo các giá trị trên phạm vi."
Jason Capriotti

1
Trình điều khiển được khởi tạo sau khi html vào vị trí của nó.
Dmitry Evseev

3
Điều gì xảy ra nếu bộ điều khiển được sử dụng lại trong các trang khác nhưng bạn chỉ muốn kích hoạt nó trên một trang cụ thể?
Roberto Linares

3
@RobertoLinares Cá nhân tôi thấy các chỉ thị là một nơi tốt hơn cho chức năng tái sử dụng. Bạn có thể có một lệnh với tham số init : <div smth on-init="doWhatever()">. Tất nhiên nó phụ thuộc vào một trường hợp sử dụng nhất định.
Dmitry Evseev

135

Thử cái này?

$scope.$on('$viewContentLoaded', function() {
    //call it here
});

5
Cảm ơn đã trả lời nhưng câu trả lời của Dmitry là một kết hợp chính xác với những gì tôi đang tìm kiếm. Nghiên cứu sâu hơn dường như đề xuất với $ viewContentLoaded
Duke Dougal 18/03/13

7
Các trường hợp sử dụng chỉ khác nhau. Tôi cũng sử dụng phương pháp của Mark.
nguyên tắc ba chiều

Đối với trường hợp sử dụng của tôi đây là một giải pháp hoàn hảo. Chúng tôi cần phải tự động chọn văn bản để khuyến khích người dùng sao chép nó. Trang có thể được tải lại / xem lại nhiều lần, vì vậy $ viewContentLoaded là một kết hợp chính xác. Cảm ơn!
Olga Gnatenko 7/07/2015

Có thể là điều này được thực hiện nhiều lần? Tôi nhận được một hành vi dường như bắt chước ...
MadPhysicist

1
Cái này không hoạt động với tôi nhưng $ scope. $ Watch đã hoạt động. Sự khác biệt chính là gì?
Burak Tokak

59

Tôi không bao giờ có $viewContentLoadedthể làm việc cho tôi và ng-initthực sự chỉ nên được sử dụng trong một ng-repeat(theo tài liệu) và việc gọi một hàm trực tiếp trong bộ điều khiển có thể gây ra lỗi nếu mã dựa trên một phần tử chưa được xác định .

Đây là những gì tôi làm và nó làm việc cho tôi:

$scope.$on('$routeChangeSuccess', function () {
  // do something
});

Trừ khi bạn đang sử dụng ui-router. Sau đó nó là:

$scope.$on('$stateChangeSuccess', function () {
  // do something
});

1
Bạn thật tuyệt vời, bạn của tôi.
taco

Chính xác những gì tôi cần. Tôi thực sự đã tìm kiếm điều này trong hai ngày!
hellojebus

3
$scope.$on('$routeChangeSuccess'kích hoạt mỗi khi các tham số trong url thay đổi ( $locationví dụ thông qua ) và do đó bạn có thể sử dụng chỉ $scope.$on('$locationChangeSuccess'. Nếu bạn cần một số kích hoạt khi tải / tải lại trang, bạn có thể sử dụng $scope.$watch('$viewContentLoaded'như được đề xuất ở đây. Nó sẽ không kích hoạt trong khi thay đổi tham số url.
Chất dẫn truyền thần kinh

sử dụng AngularJS 1.17.2, bên trong bộ điều khiển $ routeChangeSuccess hoạt động một cách đáng kinh ngạc ... adam0101 sống lâu ...
ArifMustafa

43
angular.element(document).ready(function () {

    // your code here

});

4
Phải là câu trả lời được chấp nhận, đây là cách an toàn hơn để làm điều đó
Marwen Trabelsi

Điều này là tốt nếu chúng ta không làm việc với $scopevà thay vào đó làm việc với this.
Akash

Điều này cần phải đi đâu? Tôi có nó trong mẫu của tôi và nó không bắn.
Dave

Sẽ không tốt nhất để tiêm tài liệu $ trong trường hợp này? angular.element ($ document). yet ...
jamie

4
Giải thích sẽ được đánh giá cao
Hidayt Rahman

32

Giải pháp của Dimitri / Mark không hiệu quả với tôi nhưng sử dụng hàm $ timeout dường như hoạt động tốt để đảm bảo mã của bạn chỉ chạy sau khi đánh dấu được hiển thị.

# Your controller, including $timeout

var $scope.init = function(){
 //your code
}

$timeout($scope.init)

Hy vọng nó giúp.


3
Cuối cùng. Đây là người duy nhất làm việc cho tôi. Cảm ơn.
zmirc

1
Những công việc này. Ngoài ra, đừng quên xóa thời gian chờ với $ timeout.celon (bộ đếm thời gian) trong đó bạn có var timer = $ timeout ($ scope.init, mili giây); một khi việc khởi tạo của bạn được thực hiện. Ngoài ra, tôi không nghĩ $ scope nên có một 'var' def trong mã của bạn ở trên
Emmanuel NK

Đây phải là câu trả lời được chấp nhận. Đó là người duy nhất làm việc cho tôi (đã thử tất cả các câu trả lời ở trên). Nó thậm chí hoạt động nếu bạn đang chờ tải iframe.
xin chào_fr1end

Những công việc này ! viewcontentLoaded không hoạt động với tôi
hiệp sĩ bóng đêm

28

Bạn có thể làm điều này nếu bạn muốn xem đối tượng DOM viewContentLoaded để thay đổi và sau đó làm một cái gì đó. sử dụng $ scope. $ trên hoạt động quá nhưng khác nhau, đặc biệt là khi bạn có một chế độ trang trên định tuyến của mình.

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

7
Cụ thể, nếu bạn sử dụng $ rootScope. $ Watch thay vì $ rootScope. $ Trên nó sẽ không kích hoạt thay đổi tuyến đường, vì vậy bạn có thể sử dụng logic cụ thể cho tải trang ban đầu.
csahlman

19

Bạn có thể sử dụng đối tượng cửa sổ $ của angular:

$window.onload = function(e) {
  //your magic here
}


3

Một lựa chọn khác nếu bạn có một bộ điều khiển chỉ dành riêng cho trang đó:

(function(){
    //code to run
}());

3

Khi sử dụng $ routeProvider, bạn có thể giải quyết .state và bootstrap dịch vụ của bạn. Điều này có nghĩa là, bạn sẽ tải Trình điều khiển và Chế độ xem, chỉ sau khi giải quyết Dịch vụ của bạn:

tuyến đường

 .state('nn', {
        url: "/nn",
        templateUrl: "views/home/n.html",
        controller: 'nnCtrl',
        resolve: {
          initialised: function (ourBootstrapService, $q) {

            var deferred = $q.defer();

            ourBootstrapService.init().then(function(initialised) {
              deferred.resolve(initialised);
            });
            return deferred.promise;
          }
        }
      })

Dịch vụ

function ourBootstrapService() {

 function init(){ 
    // this is what we need
 }
}

3

Tìm thấy Dmitry Evseev trả lời khá hữu ích.

Trường hợp 1: Chỉ sử dụng angularJs:
Để thực thi một phương thức khi tải trang, bạn có thể sử dụng ng-inittrong chế độ xem và khai báo phương thức init trong bộ điều khiển, đã nói rằng không nên sử dụng chức năng nặng hơn, theo Tài liệu góc trên ng-init :

Lệnh này có thể bị lạm dụng để thêm số lượng logic không cần thiết vào các mẫu của bạn. Chỉ có một vài cách sử dụng ngInit thích hợp, chẳng hạn như đối với các thuộc tính đặc biệt của ngRepeat, như được thấy trong bản demo dưới đây; và để tiêm dữ liệu thông qua kịch bản phía máy chủ. Bên cạnh một vài trường hợp, bạn nên sử dụng bộ điều khiển thay vì ngInit để khởi tạo giá trị trên một phạm vi.

HTML:

<div ng-controller="searchController()">
    <!-- renaming view code here, including the search box and the buttons -->
</div>

Điều khiển:

app.controller('SearchCtrl', function(){

    var doSearch = function(keyword){
        //Search code here
    }

    doSearch($routeParams.searchKeyword);
})

Cảnh báo: Không sử dụng bộ điều khiển này cho chế độ xem khác có nghĩa cho một mục đích khác vì nó cũng sẽ khiến phương thức tìm kiếm được thực thi ở đó.

Trường hợp 2: Sử dụng Ionic:
Đoạn mã trên sẽ hoạt động, chỉ cần đảm bảo bộ đệm xem bị vô hiệu hóa route.jsnhư:

route.js

.state('app', {
    url           : '/search',
    cache         : false, //disable caching of the view here
    templateUrl   : 'templates/search.html'   ,
    controller    : 'SearchCtrl'
  })

Hi vọng điêu nay co ich


1
Điều này chỉ có một lên và ở dưới cùng, vui mừng vì tôi đã đi xuống, điều cache: falseđó đã làm cho tôi - cảm ơn!
Rani Kheir

3

Tôi đã có cùng một vấn đề và chỉ có giải pháp này hoạt động với tôi (nó chạy một chức năng sau khi tải xong DOM). Tôi sử dụng điều này để cuộn để neo sau khi trang đã được tải:

angular.element(window.document.body).ready(function () {

                        // Your function that runs after all DOM is loaded

                    });

2

Bạn có thể lưu kết quả tìm kiếm trong một dịch vụ chung có thể sử dụng từ mọi nơi và không rõ ràng khi điều hướng đến trang khác và sau đó bạn có thể đặt kết quả tìm kiếm với dữ liệu đã lưu cho nhấp chuột vào nút quay lại

function search(searchTerm) {
    // retrieve the data here;
    RetrievedData = CallService();
    CommonFunctionalityService.saveSerachResults(RetrievedData);
} 

Cho backbutton của bạn

function Backbutton() {
    RetrievedData = CommonFunctionalityService.retrieveResults();
}

0

gọi các phương thức ban đầu bên trong chức năng tự khởi tạo.

(function initController() {

    // do your initialize here

})();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.