¿Cómo ejecutar la función del controlador AngularJS en la carga de la página?

360

Actualmente tengo una página Angular.js que permite la búsqueda y muestra resultados. El usuario hace clic en un resultado de búsqueda, luego hace clic en el botón Atrás. Quiero que los resultados de la búsqueda se muestren nuevamente, pero no puedo averiguar cómo activar la búsqueda para que se ejecute. Aquí está el detalle:

  • Mi página Angular.js es una página de búsqueda, con un campo de búsqueda y un botón de búsqueda. El usuario puede escribir manualmente una consulta y presionar un botón y se activa una consulta ajax y se muestran los resultados. Actualizo la URL con el término de búsqueda. Todo eso funciona bien.
  • El usuario hace clic en el resultado de la búsqueda y es llevado a una página diferente, que también funciona bien.
  • El usuario hace clic en el botón Atrás, vuelve a mi página de búsqueda angular y se muestra la URL correcta, incluido el término de búsqueda. Todo funciona bien.
  • He vinculado el valor del campo de búsqueda al término de búsqueda en la URL, por lo que contiene el término de búsqueda esperado. Todo funciona bien.

¿Cómo consigo que la función de búsqueda se ejecute nuevamente sin que el usuario tenga que presionar el "botón de búsqueda"? Si fuera jquery, ejecutaría una función en la función documentready. No puedo ver el equivalente de Angular.js.

Duque dugal
fuente
estás usando $routepProvider? Úselo para conectarse al servicio en su aplicación que proporciona datos para los resultados de búsqueda. No pienses en document.readytérminos como con jQuery. Difícil de ayudar mucho sin ver cómo has conectado la búsqueda actualmente
charlietfl

Respuestas:

430

Por un lado, como @ Mark-Rajcok dijo que puedes salirte con la tuya con la función interna privada:

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

También puedes echar un vistazo a la directiva ng-init . La implementación será muy parecida a:

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

Pero tenga cuidado al respecto, ya que la documentación angular implica (desde v1.2) NO usar ng-initpara eso. Sin embargo, depende de la arquitectura de su aplicación.

Solía ng-initcuando quería pasar un valor del back-end a la aplicación angular:

<div data-ng-controller="myCtrl" data-ng-init="init('%some_backend_value%')"></div>
Dmitry Evseev
fuente
66
@Duke, ¿no puedes simplemente poner el contenido de la función init () en la parte inferior de tu controlador? Es decir, ¿por qué necesita usar ng-init y tener una función init ()? Cuando el usuario presiona el botón Atrás, supongo que está cambiando de vista, por lo tanto, myCtrlse crea y ejecuta un nuevo controlador.
Mark Rajcok
24
Si bien esta solución funciona, rechacé porque la documentación ng-init desaconseja esto. Específicamente, "El único uso apropiado de ngInit para aliasar propiedades especiales de ngRepeat, como se ve en la demostración a continuación. Además de este caso, debe usar controladores en lugar de ngInit para inicializar valores en un ámbito".
Jason Capriotti
1
El controlador se instancia después de que html esté en su lugar.
Dmitry Evseev
3
¿Qué sucede si el controlador se reutiliza en otras páginas pero solo desea activarlo en una página específica?
Roberto Linares
3
@RobertoLinares Personalmente, creo que las directivas son un lugar mejor para la funcionalidad reutilizable. Usted puede tener una directiva con un parámetro init: <div smth on-init="doWhatever()">. Por supuesto, depende de un determinado caso de uso.
Dmitry Evseev
135

¿Prueba esto?

$scope.$on('$viewContentLoaded', function() {
    //call it here
});
principio holográfico
fuente
55
Gracias por la respuesta, pero la respuesta de Dmitry coincidía exactamente con lo que estaba buscando. La investigación adicional parece recomendar contra $ viewContentLoaded
Duke Dougal
77
Los casos de uso son simplemente diferentes. También uso el método de Mark todo el tiempo.
principio holográfico
Para mi caso de uso, esta fue una solución perfecta. Necesitábamos seleccionar automáticamente el texto para alentar al usuario a copiarlo. La página podría volver a cargarse / revisarse muchas veces, por lo que $ viewContentLoaded era una coincidencia exacta. ¡Gracias!
Olga Gnatenko
¿Es posible que esto se ejecute varias veces? Tengo un comportamiento que parece estar imitando eso ...
MadPhysicist
1
Este no funcionó para mí, pero $ scope. $ Watch funcionó. ¿Cual es la diferencia principal?
Burak Tokak
59

Nunca podría $viewContentLoadedtrabajar para mí, y ng-initrealmente solo debería usarse en un ng-repeat(de acuerdo con la documentación), y también llamar a una función directamente en un controlador puede causar errores si el código se basa en un elemento que aún no se ha definido .

Esto es lo que hago y me funciona:

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

A menos que lo estés usando ui-router. Entonces es:

$scope.$on('$stateChangeSuccess', function () {
  // do something
});
adam0101
fuente
1
Eres asombroso, mi amigo.
taco
Exactamente lo que necesitaba. ¡Literalmente estuve buscando esto por dos días!
hellojebus
3
$scope.$on('$routeChangeSuccess'se dispara cada vez que se modifican los parámetros en la URL (a través de, $locationpor ejemplo) y, por lo tanto, puede usar solo $scope.$on('$locationChangeSuccess'. Si necesita algún disparador en la carga / recarga de la página, puede usarlo $scope.$watch('$viewContentLoaded'como se sugirió aquí. No se disparará durante los cambios de parámetros de url.
Neurotransmisor
usando AngularJS 1.17.2, controlador interno $ routeChangeSuccess funcionó increíblemente ... larga vida adam0101 ...
ArifMustafa
43
angular.element(document).ready(function () {

    // your code here

});
Carlos Trujillo
fuente
44
Debe ser la respuesta aceptada, esta es la forma más segura de hacerlo
Marwen Trabelsi
Esto es bueno si no trabajamos $scopey en su lugar trabajamos this.
Akash
¿A dónde tiene que ir esto? Lo tengo en mi plantilla y no se está disparando.
Dave
¿No sería mejor inyectar $ document en este caso? angular.element ($ document) .ready ...
jamie
55
Explicación sería apreciada
Hidayt Rahman
32

La solución de Dimitri / Mark no funcionó para mí, pero el uso de la función $ timeout parece funcionar bien para garantizar que su código solo se ejecute después de que se procese el marcado.

# Your controller, including $timeout

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

$timeout($scope.init)

Espero eso ayude.

guico
fuente
3
Finalmente. Este es el único que funcionó para mí. Gracias.
zmirc
1
Esto funciona. Además, no olvide borrar el tiempo de espera con $ timeout.cancel (timer) donde tiene var timer = $ timeout ($ scope.init, milisegundos); una vez que se complete su inicialización. Además, no creo que $ scope deba tener una 'var' def en su código anterior
Emmanuel NK
Esta debería ser la respuesta aceptada. Fue el único que funcionó para mí (probé todas las respuestas anteriores). Incluso funciona si está esperando que se cargue un iframe.
hello_fr1end
Esto funciona ! viewcontentLoaded no funcionó para mí
caballero oscuro
28

Puede hacer esto si desea ver el objeto viewContentLoaded DOM para cambiar y luego hacer algo. el uso de $ scope. $ on también funciona, pero de manera diferente, especialmente cuando tiene un modo de página en su enrutamiento.

 $scope.$watch('$viewContentLoaded', function(){
    // do something
 });
CodeOverRide
fuente
77
Específicamente, si usa $ rootScope. $ Watch en lugar de $ rootScope. $ On, no se activará en los cambios de ruta, por lo que puede usar una lógica específica para la carga de la página inicial.
csahlman
19

Puede usar el objeto $ window de angular:

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

Otra alternativa más si tiene un controlador específico para esa página:

(function(){
    //code to run
}());
Chipe
fuente
3

Al usar $ routeProvider puede resolver en .state y arrancar su servicio. Es decir, va a cargar Controlador y Vista, solo después de resolver su Servicio:

Ui-rutas

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

Servicio

function ourBootstrapService() {

 function init(){ 
    // this is what we need
 }
}
Leo Lanese
fuente
3

Encontramos la respuesta de Dmitry Evseev bastante útil.

Caso 1: Uso de angularJs solo:
para ejecutar un método en la carga de la página, puede usar ng-initen la vista y declarar el método init en el controlador, habiendo dicho que no se recomienda el uso de una función más pesada, según los documentos angulares en ng-init :

Se puede abusar de esta directiva para agregar cantidades innecesarias de lógica a sus plantillas. Solo hay unos pocos usos apropiados de ngInit, como para aliasar propiedades especiales de ngRepeat, como se ve en la demostración a continuación; y para inyectar datos a través de secuencias de comandos del lado del servidor. Además de estos pocos casos, debe usar controladores en lugar de ngInit para inicializar valores en un ámbito.

HTML:

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

Controlador:

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

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

    doSearch($routeParams.searchKeyword);
})

Advertencia: No utilice este controlador para otra vista destinada a una intención diferente, ya que también hará que el método de búsqueda se ejecute allí.

Caso 2: Uso de Ionic:
el código anterior funcionará, solo asegúrese de que la vista de la memoria caché esté deshabilitada route.jscomo:

route.js

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

Espero que esto ayude

Kailas
fuente
1
Esto solo tenía uno arriba y estaba en la parte inferior, contento de haber bajado hasta el final, lo cache: falsehizo por mí, ¡gracias!
Rani Kheir
3

Tuve el mismo problema y solo esta solución funcionó para mí (ejecuta una función después de que se haya cargado un DOM completo). Lo uso para desplazarme para anclar después de cargar la página:

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

                        // Your function that runs after all DOM is loaded

                    });
Ginko Balboa
fuente
2

Puede guardar los resultados de búsqueda en un servicio común que puede usar desde cualquier lugar y no se borra cuando navega a otra página, y luego puede configurar los resultados de búsqueda con los datos guardados para hacer clic en el botón Atrás

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

Para tu botón trasero

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

llamar a métodos iniciales dentro de la función de autoinicialización.

(function initController() {

    // do your initialize here

})();
Uditha Prasad
fuente