Як виконати функцію контролера AngularJS при завантаженні сторінки?


359

На даний момент у мене є сторінка Angular.js, яка дозволяє шукати та відображати результати. Користувач натискає на результат пошуку, потім натискає кнопку назад. Я хочу, щоб результати пошуку відображалися знову, але я не можу розробити, як запустити пошук для виконання. Ось деталь:

  • Моя сторінка Angular.js - це сторінка пошуку з полем пошуку та кнопкою пошуку. Користувач може ввести запит вручну і натиснути кнопку, і запит ajax запускається, і результати відображаються. Я оновлюю URL-адресу за допомогою пошукового терміну. Це все добре працює.
  • Користувач натискає на результат пошуку і переходить на іншу сторінку - це теж добре.
  • Користувач натискає кнопку назад, повертається на мою кутову сторінку пошуку, і відображається правильна URL-адреса, включаючи пошуковий термін. Все працює чудово.
  • Я прив’язав значення пошукового поля до пошукового терміна в URL-адресі, тому він містить очікуваний пошуковий термін. Все працює чудово.

Як змусити функцію пошуку знову виконати, не потребуючи натискання «кнопки пошуку» користувачеві? Якщо б це було jquery, то я би виконував функцію у функції, яка вже документує. Я не можу побачити еквівалент Angular.js.


ти використовуєш $routepProvider? Використовуйте його для підключення до служби у вашій програмі, яка надає дані для результатів пошуку. Не думайте з document.readyточки зору jQuery. Важко багато допомогти, не бачивши, як ви шукаєте підключений пошук
charlietfl

Відповіді:


430

З одного боку, як @ Mark-Rajcok сказав, що ви можете просто піти з приватної внутрішньої функції:

// 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();

Також ви можете поглянути на директиву ng-init . Впровадження буде приблизно таким:

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

Але подбайте про це, оскільки кутова документація передбачає (оскільки v1.2) НЕ використовувати ng-initдля цього. Однак, це залежить від архітектури вашої програми.

Я використовував, ng-initколи хотів передати значення з "бек-енду" в кутовий додаток:

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

6
@Duke, ти не можеш просто поставити вміст функції init () внизу контролера? Тобто, для чого потрібно використовувати ng-init і мати функцію init ()? Коли користувач натискає кнопку "назад", я припускаю, що ви перемикаєте подання, отже myCtrl, створюється і виконується новий контролер.
Марк Райкок

24
Хоча це рішення працює, я подав заяву, оскільки документація на ng-init радить цьому. Зокрема, "Єдине належне використання ngInit для вилучення спеціальних властивостей ngRepeat, як видно з демонстрації нижче. Крім цього, для ініціалізації значень у області застосування слід використовувати контролери, а не ngInit."
Джейсон Капріотті

1
Контролер інстанціюється після того, як html знаходиться на його місці.
Дмитро Євсєєв,

3
Що робити, якщо контролер повторно використовувати на інших сторінках, але ви просто хочете запустити його на певну сторінку?
Роберто Лінарес

3
@RobertoLinares Я особисто вважаю, що директиви є кращим місцем для багаторазового використання. Ви можете мати директиву з параметром ініціалізації: <div smth on-init="doWhatever()">. Звичайно, це залежить від певного випадку використання.
Дмитро Євсєєв

135

Спробуйте це?

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

5
Дякую за відповідь, але відповідь Дмитра була точною відповідністю тому, що я шукаю. Подальше дослідження, здавалося, рекомендує проти $ viewContentLoaded
Герцог Дугал

7
Випадки використання просто різні. Я постійно використовую метод Марка.
голографічний принцип

Для мого випадку це було ідеальним рішенням. Нам потрібно було автоматично вибрати текст, щоб заохотити користувача скопіювати його. Сторінку можна було перезавантажувати / переглядати багато разів, тому $ viewContentLoaded було точно збігом. Дякую!
Ольга Гнатенко

Чи можливо, що це виконується кілька разів? Я отримую поведінку, яка, схоже, імітує це ...
MadPhysicist

1
Цей не працював для мене, але $ range. $ Watch працював. У чому головна відмінність?
Бурак Токак

59

Я ніколи не міг $viewContentLoadedби працювати на мене, і його ng-initслід використовувати лише в ng-repeat(відповідно до документації), а також виклик функції безпосередньо в контролері може призвести до помилок, якщо код покладається на елемент, який ще не був визначений .

Це те, що я роблю, і це працює для мене:

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

Якщо ви не використовуєте ui-router. Тоді це:

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

1
Ти приголомшливий, мій друже.
тако

Саме те, що мені було потрібно. Я буквально шукав цього два дні!
hellojebus

3
$scope.$on('$routeChangeSuccess'запускає кожен раз, коли параметри в URL-адресі змінюються ( $locationнаприклад, наприклад), і таким чином ви можете просто використовувати $scope.$on('$locationChangeSuccess'. Якщо вам потрібен якийсь тригер при завантаженні / перезавантаженні сторінки, ви можете використовувати, $scope.$watch('$viewContentLoaded'як було запропоновано тут. Він не запуститься під час зміни параметрів URL.
Нейромедіатор

використовуючи AngularJS 1.17.2, всередині контролера $ routeChangeSuccess працював дивовижно ... давно живе adam0101 ...
ArifMustafa

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

    // your code here

});

4
Має бути прийнятою відповіддю, це безпечніший спосіб зробити це
Марвен Трабелсі

Це добре, якщо ми не працюємо $scopeі замість цього працюємо this.
Акаш

Куди це потрібно піти? У мене це є в моєму шаблоні, і він не стріляє.
Дейв

Не найкраще буде вводити $ документ у цьому випадку? angular.element ($ документ). вже ...
jamie

4
Пояснення будуть вдячні
Хідайт Рахман

32

Рішення Димитрія / Марка не працювало для мене, але використання функції $ timeout, здається, працює добре, щоб забезпечити, що ваш код працює лише після надання розмітки.

# Your controller, including $timeout

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

$timeout($scope.init)

Сподіваюся, це допомагає.


3
Нарешті. Це єдиний, хто працював на мене. Дякую.
zmirc

1
Це працює. Також не забудьте очистити час очікування за допомогою $ timeout.cancel (таймер), де у вас є var timer = $ timeout ($ range.init, мілісекунд); як тільки ваша ініціалізація виконана. Крім того, я не думаю, що в $ range має бути значення 'var' у вашому коді вище
Emmanuel NK

Це має бути прийнятою відповіддю. Це був єдиний, хто працював на мене (спробував усі відповіді вище). Це навіть працює, якщо ви чекаєте завантаження iframe.
hello_fr1end

Це працює! viewcontentLoaded для мене не працював
темний лицар

28

Це можна зробити, якщо ви хочете переглянути об'єкт DOM viewContentLoaded, щоб змінитися, а потім зробити щось. використання $ range. $ для роботи теж працює, але по-різному, особливо коли у вас є режим однієї сторінки.

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

7
Зокрема, якщо ви використовуєте $ rootScope. $ Watch замість $ rootScope. $ Він не запускатиме зміни маршруту, тому ви можете використовувати логіку, характерну для початкового завантаження сторінки.
csahlman

19

Ви можете використовувати $ window object:

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


3

Ще одна альтернатива, якщо у вас є контролер, специфічний саме для цієї сторінки:

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

3

Використовуючи $ routeProvider, ви можете вирішити на .state і завантажувати свою послугу. Це означає, що ви збираєтеся завантажити Controller і View, тільки після вирішення послуги:

ui-маршрути

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

Сервіс

function ourBootstrapService() {

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

3

Знайдений відповідь Дмитра Євсєєва досить корисний.

Випадок 1: Використання лише angularJs:
Щоб виконати метод на завантаженні сторінки, ви можете використовувати ng-initу поданні та оголошувати метод init у контролері, сказавши, що використання більш важкої функції не рекомендується, відповідно до кутових Документів у ng-init :

Цю директиву можна зловживати, щоб додати зайві кількості логіки у ваші шаблони. Існує лише кілька відповідних застосувань ngInit, наприклад, для псевдонімування спеціальних властивостей ngRepeat, як видно з демонстрації нижче; і для введення даних за допомогою сценарію на стороні сервера. Окрім цих кількох випадків, вам слід використовувати контролери, а не ngInit для ініціалізації значень на області.

HTML:

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

Контролер:

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

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

    doSearch($routeParams.searchKeyword);
})

Попередження: Не використовуйте цей контролер для іншого виду, призначеного для іншого наміру, оскільки це призведе до того, що спосіб пошуку буде виконаний і там.

Випадок 2: Використання Ionic:
Наведений вище код буде працювати, просто переконайтеся, що кеш перегляду вимкнено у route.jsвигляді:

route.js

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

Сподіваюсь, це допомагає


1
Це був тільки один вгору і був у самому дні, радий, що я пройшов увесь шлях вниз, cache: falseзробив це для мене - дякую!
Рані Хейр

3

У мене була така ж проблема, і для мене працювало тільки це рішення (воно виконує функцію після завантаження повної DOM). Я використовую це для прокрутки до прив'язки після завантаження сторінки:

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

                        // Your function that runs after all DOM is loaded

                    });

2

Ви можете зберегти результати пошуку в загальній службі, яку можна використовувати з будь-якого місця та не очищати при переході на іншу сторінку, а потім ви можете встановити результати пошуку із збереженими даними для натискання кнопки "Назад".

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

Для вашої задньої кнопки

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

0

виклик початкових методів всередині функції самоініціалізації.

(function initController() {

    // do your initialize here

})();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.