Как выполнить функцию контроллера 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
});
adam0101
источник
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)

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

guico
источник
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
 });
CodeOverRide
источник
7
В частности, если вы используете $ rootScope. $ Watch вместо $ rootScope. $ On, он не сработает при изменении маршрута, поэтому вы можете использовать логику, специфичную для начальной загрузки страницы.
csahlman
19

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

$window.onload = function(e) {
  //your magic here
}
McGraw
источник
3

Еще одна альтернатива, если у вас есть контроллер, специфичный для этой страницы:

(function(){
    //code to run
}());
Chipe
источник
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();
}
Heshan
источник
0

вызовите начальные методы внутри функции собственной инициализации.

(function initController() {

    // do your initialize here

})();
Удита Прасад
источник