Как выполнить функцию контроллера AngularJS при загрузке страницы?


360

В настоящее время у меня есть страница Angular.js, которая позволяет искать и отображать результаты. Пользователь нажимает на результат поиска, а затем нажимает кнопку назад. Я хочу, чтобы результаты поиска снова отображались, но я не могу понять, как запустить поиск. Вот деталь:

  • Моя страница Angular.js - это страница поиска с полем поиска и кнопкой поиска. Пользователь может вручную ввести запрос и нажать кнопку, и запрос ajax запускается, и результаты отображаются. Я обновляю URL поисковым запросом. Это все работает отлично.
  • Пользователь нажимает на результат поиска и попадает на другую страницу - это тоже хорошо работает.
  • Пользователь нажимает кнопку «Назад» и возвращается на мою страницу углового поиска, и отображается правильный URL-адрес, включая условие поиска. Все работает отлично.
  • Я связал значение поля поиска с поисковым термином в URL, поэтому он содержит ожидаемый поисковый термин. Все работает отлично.

Как заставить функцию поиска снова выполняться без необходимости нажимать кнопку «Поиск»? Если бы это был jquery, то я бы выполнил функцию в функции documentready. Я не вижу аналога 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
};

Но позаботьтесь об этом, поскольку угловая документация подразумевает (начиная с версии 1.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
— Duke Dougal

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

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

Возможно ли, что это выполняется несколько раз? Я получаю поведение, которое, кажется, имитирует это ...
— MadPhysicist

1
Этот не работал для меня, но $ scope. $ 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.
— Акаш

Куда это нужно идти? У меня есть это в моем шаблоне, и это не стрельба.
— Дэйв

Не лучше ли будет вводить $ document в этом случае? angular.element ($ document) .ready ...
— Джейми

5
— Мы

32

Решение Димитрия / Марка у меня не сработало, но использование функции $ timeout, кажется, работает хорошо, чтобы гарантировать, что ваш код запускается только после того, как разметка отрисована.

# Your controller, including $timeout

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

$timeout($scope.init)

Надеюсь, поможет.


3
В заключение. Это единственный, который работал на меня. Спасибо.
— zmirc

1
Это работает. Также не забудьте очистить тайм-аут с помощью $ timeout.cancel (timer), где у вас есть var timer = $ timeout ($ scope.init, milliseconds); как только ваша инициализация сделана. Кроме того, я не думаю, что $ scope должен иметь в вашем коде def 'var'
— Эммануэль НК

Это должен быть принятый ответ. Это был единственный, который работал для меня (попробовал все ответы выше). Это даже работает, если вы ожидаете загрузки iframe.
— hello_fr1end

Это работает ! viewcontentLoaded не работает для меня
— темный рыцарь

28

Вы можете сделать это, если хотите посмотреть, как изменяется объект DOM viewContentLoaded, а затем что-то сделать. Использование $ scope. $ on тоже работает, но по-разному, особенно если в маршрутизации используется одностраничный режим.

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

7
В частности, если вы используете $ rootScope. $ Watch вместо $ rootScope. $ On, он не сработает при изменении маршрута, поэтому вы можете использовать логику, специфичную для начальной загрузки страницы.
— csahlman

19

Вы можете использовать объект $ window angular:

$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: Использование одних только angularJ:
Чтобы выполнить метод при загрузке страницы, вы можете использовать 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.jsas:

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.