redireccionar insertar imagenes div combos cargar agregar angularjs angularjs-directive

angularjs - insertar - ng src angular



Angularjs cargando la pantalla en la solicitud de ajax (15)

Usando Angularjs, necesito mostrar una pantalla de carga (un spinner simple) hasta que se complete la solicitud de ajax. Por favor sugiera cualquier idea con un fragmento de código.


Aquí ejemplo de interceptor simple, puse el mouse en espera cuando ajax se inicia y lo configuro en automático cuando ajax termina.

$httpProvider.interceptors.push(function($document) { return { ''request'': function(config) { // here ajax start // here we can for example add some class or show somethin $document.find("body").css("cursor","wait"); return config; }, ''response'': function(response) { // here ajax ends //here we should remove classes added on request start $document.find("body").css("cursor","auto"); return response; } }; });

El código debe ser agregado en la aplicación config app.config . Mostré cómo cambiar el mouse en el estado de carga, pero allí es posible mostrar / ocultar cualquier contenido del cargador, o agregar, eliminar algunas clases de CSS que muestran el cargador.

Interceptor se ejecutará en cada llamada ajax, por lo que no es necesario crear variables booleanas especiales ($ scope.loading = true / false, etc.) en cada llamada http.

Interceptor está utilizando construido en angular jqLite https://docs.angularjs.org/api/ng/function/angular.element por lo que no es necesario Jquery.


Aquí hay un ejemplo. Utiliza el método simple ng-show con un bool.

HTML

<div ng-show="loading" class="loading"><img src="...">LOADING...</div> <div ng-repeat="car in cars"> <li>{{car.name}}</li> </div> <button ng-click="clickMe()" class="btn btn-primary">CLICK ME</button>

ANGULARJS

$scope.clickMe = function() { $scope.loading = true; $http.get(''test.json'') .success(function(data) { $scope.cars = data[0].cars; $scope.loading = false; }); }

Por supuesto, puede mover el código html de la caja de carga a una directiva y luego usar $ watch en $ scope.loading. En ese caso:

HTML :

<loading></loading>

DIRECTIVA DE ANGULARJS :

.directive(''loading'', function () { return { restrict: ''E'', replace:true, template: ''<div class="loading"><img src="..."/>LOADING...</div>'', link: function (scope, element, attr) { scope.$watch(''loading'', function (val) { if (val) $(element).show(); else $(element).hide(); }); } } })

PLUNK : http://plnkr.co/edit/AI1z21?p=preview


Creé un poco la respuesta de @DavidLin para simplificarlo, eliminando cualquier dependencia de jQuery en la directiva. Puedo confirmar que esto funciona como lo uso en una aplicación de producción

function AjaxLoadingOverlay($http) { return { restrict: ''A'', link: function ($scope, $element, $attributes) { $scope.loadingOverlay = false; $scope.isLoading = function () { return $http.pendingRequests.length > 0; }; $scope.$watch($scope.isLoading, function (isLoading) { $scope.loadingOverlay = isLoading; }); } }; }

Uso un ng-show lugar de una llamada jQuery para ocultar / mostrar el <div> .

Aquí está el <div> que coloqué justo debajo de la etiqueta <body> apertura:

<div ajax-loading-overlay class="loading-overlay" ng-show="loadingOverlay"> <img src="Resources/Images/LoadingAnimation.gif" /> </div>

Y aquí está el CSS que proporciona la superposición para bloquear la interfaz de usuario mientras se realiza una llamada de $ http:

.loading-overlay { position: fixed; z-index: 999; height: 2em; width: 2em; overflow: show; margin: auto; top: 0; left: 0; bottom: 0; right: 0; } .loading-overlay:before { content: ''''; display: block; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.3); } /* :not(:required) hides these rules from IE9 and below */ .loading-overlay:not(:required) { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; }

El crédito CSS va a @Steve Seeger''s - su publicación: https://.com/a/35470281/335545


Crea una directiva con los atributos mostrar y tamaño (también puedes agregar más)

app.directive(''loader'',function(){ return { restrict:''EA'', scope:{ show : ''@'', size : ''@'' }, template : ''<div class="loader-container"><div class="loader" ng-if="show" ng-class="size"></div></div>'' } })

y en html uso como

<loader show="{{loader1}}" size="sm"></loader>

En la variable show , pasa verdadero cuando se está ejecutando cualquier promesa y la convierte en falsa cuando se completa la solicitud. Demostración activa: ejemplo de directiva de Angular Loader demo en JsFiddle


En lugar de configurar una variable de ámbito para indicar el estado de carga de datos, es mejor tener una directiva que haga todo por usted:

angular.module(''directive.loading'', []) .directive(''loading'', [''$http'' ,function ($http) { return { restrict: ''A'', link: function (scope, elm, attrs) { scope.isLoading = function () { return $http.pendingRequests.length > 0; }; scope.$watch(scope.isLoading, function (v) { if(v){ elm.show(); }else{ elm.hide(); } }); } }; }]);

Con esta directiva, todo lo que necesita hacer es darle a cualquier elemento de animación de carga un atributo de ''carga'':

<div class="loading-spiner-holder" data-loading ><div class="loading-spiner"><img src="..." /></div></div>

Puede tener múltiples spinners de carga en la página. dónde y cómo distribuir esos hilanderos depende de usted y la directiva simplemente lo encenderá / apagará automáticamente.


En referencia a esta respuesta

https://.com/a/17144634/4146239

Para mí es la mejor solución, pero hay una forma de evitar el uso de jQuery.

.directive(''loading'', function () { return { restrict: ''E'', replace:true, template: ''<div class="loading"><img src="http://www.nasa.gov/multimedia/videogallery/ajax-loader.gif" width="20" height="20" />LOADING...</div>'', link: function (scope, element, attr) { scope.$watch(''loading'', function (val) { if (val) scope.loadingStatus = ''true''; else scope.loadingStatus = ''false''; }); } } }) .controller(''myController'', function($scope, $http) { $scope.cars = []; $scope.clickMe = function() { scope.loadingStatus = ''true'' $http.get(''test.json'') .success(function(data) { $scope.cars = data[0].cars; $scope.loadingStatus = ''false''; }); } });

<body ng-app="myApp" ng-controller="myController" ng-init="loadingStatus=''true''"> <loading ng-show="loadingStatus" ></loading> <div ng-repeat="car in cars"> <li>{{car.name}}</li> </div> <button ng-click="clickMe()" class="btn btn-primary">CLICK ME</button> </body>

Debe reemplazar $ (elemento) .show (); y (elemento) .show (); con $ scope.loadingStatus = ''true''; y $ scope.loadingStatus = ''false'';

Entonces, necesita usar esta variable para establecer el atributo ng-show del elemento.


Incluye esto en tu "app.config":

$httpProvider.interceptors.push(''myHttpInterceptor'');

Y agrega este código:

app.factory(''myHttpInterceptor'', function ($q, $window,$rootScope) { $rootScope.ActiveAjaxConectionsWithouthNotifications = 0; var checker = function(parameters,status){ //YOU CAN USE parameters.url TO IGNORE SOME URL if(status == "request"){ $rootScope.ActiveAjaxConectionsWithouthNotifications+=1; $(''#loading_view'').show(); } if(status == "response"){ $rootScope.ActiveAjaxConectionsWithouthNotifications-=1; } if($rootScope.ActiveAjaxConectionsWithouthNotifications<=0){ $rootScope.ActiveAjaxConectionsWithouthNotifications=0; $(''#loading_view'').hide(); } }; return { ''request'': function(config) { checker(config,"request"); return config; }, ''requestError'': function(rejection) { checker(rejection.config,"request"); return $q.reject(rejection); }, ''response'': function(response) { checker(response.config,"response"); return response; }, ''responseError'': function(rejection) { checker(rejection.config,"response"); return $q.reject(rejection); } }; });


La mejor forma de hacerlo es usar interceptores de respuesta junto con directivas personalizadas. Y el proceso puede mejorarse aún más utilizando el mecanismo pub / sub utilizando los métodos $ rootScope. $ Broadcast y $ rootScope. $ On .

Como todo el proceso está documentado en un artículo de blog bien escrito, no voy a repetirlo aquí otra vez. Consulte ese artículo para obtener su implementación necesaria.


Si está utilizando Restangular (que es increíble) puede crear una animación durante las llamadas de API. Aquí está mi solución. Agregue un interceptor de respuesta y un interceptor de solicitud que envíe una transmisión de rootscope. Luego crea una directiva para escuchar esa respuesta y solicitud .:

angular.module(''mean.system'') .factory(''myRestangular'',[''Restangular'',''$rootScope'', function(Restangular,$rootScope) { return Restangular.withConfig(function(RestangularConfigurer) { RestangularConfigurer.setBaseUrl(''http://localhost:3000/api''); RestangularConfigurer.addResponseInterceptor(function(data, operation, what, url, response, deferred) { var extractedData; // .. to look for getList operations if (operation === ''getList'') { // .. and handle the data and meta data extractedData = data.data; extractedData.meta = data.meta; } else { extractedData = data.data; } $rootScope.$broadcast(''apiResponse''); return extractedData; }); RestangularConfigurer.setRequestInterceptor(function (elem, operation) { if (operation === ''remove'') { return null; } return (elem && angular.isObject(elem.data)) ? elem : {data: elem}; }); RestangularConfigurer.setRestangularFields({ id: ''_id'' }); RestangularConfigurer.addRequestInterceptor(function(element, operation, what, url) { $rootScope.$broadcast(''apiRequest''); return element; }); }); }]);

Aquí está la directiva:

angular.module(''mean.system'') .directive(''smartLoadingIndicator'', function($rootScope) { return { restrict: ''AE'', template: ''<div ng-show="isAPICalling"><p><i class="fa fa-gear fa-4x fa-spin"></i>&nbsp;Loading</p></div>'', replace: true, link: function(scope, elem, attrs) { scope.isAPICalling = false; $rootScope.$on(''apiRequest'', function() { scope.isAPICalling = true; }); $rootScope.$on(''apiResponse'', function() { scope.isAPICalling = false; }); } }; }) ;


También hay una bonita demostración que muestra cómo puedes usar la animación de Angularjs en tu proyecto.
el enlace está aquí
http://yearofmoo-articles.github.io/angularjs-animation-article/app/#/ng-repeat (Ver la esquina superior izquierda) .
Es una fuente abierta. aquí está el enlace para descargar
https://github.com/yearofmoo-articles/AngularJS-Animation-Article
Y aquí está el enlace para el tutorial;
http://www.yearofmoo.com/2013/04/animation-in-angularjs.html
Mi punto es, adelante y descargue los archivos fuente y luego vea cómo han implementado el spinner. Podrían haber usado un enfoque un poco mejor. Por lo tanto, revisa este proyecto.


Usa angular-busy :

Agregue cgBusy a su aplicación / módulo:

angular.module(''your_app'', [''cgBusy'']);

Añada su promesa al scope :

function MyCtrl($http, User) { //using $http this.isBusy = $http.get(''...''); //if you have a User class based on $resource this.isBusy = User.$save(); }

En tu plantilla html:

<div cg-busy="$ctrl.isBusy"></div>


Yo uso ngProgress para esto.

Agregue ''ngProgress'' a sus dependencias una vez que haya incluido los archivos de script / css en su HTML. Una vez que lo haga, puede configurar algo como esto, que se activará cuando se detecte un cambio de ruta.

angular.module(''app'').run(function($rootScope, ngProgress) { $rootScope.$on(''$routeChangeStart'', function(ev,data) { ngProgress.start(); }); $rootScope.$on(''$routeChangeSuccess'', function(ev,data) { ngProgress.complete(); }); });

Para las solicitudes AJAX puede hacer algo como esto:

$scope.getLatest = function () { ngProgress.start(); $http.get(''/latest-goodies'') .success(function(data,status) { $scope.latest = data; ngProgress.complete(); }) .error(function(data,status) { ngProgress.complete(); }); };

Simplemente recuerde agregar ''ngProgress'' a las dependencias de los controladores antes de hacerlo. Y si está haciendo múltiples solicitudes AJAX use una variable incremental en el alcance de la aplicación principal para realizar un seguimiento cuando sus solicitudes AJAX hayan finalizado antes de llamar a ''ngProgress.complete ();''.


el uso de pendingRequests no es correcto porque, como se menciona en la documentación de Angular, esta propiedad está destinada principalmente para fines de depuración.

Lo que recomiendo es usar un interceptor para saber si hay alguna llamada Async activa.

module.config([''$httpProvider'', function ($httpProvider) { $httpProvider.interceptors.push(function ($q, $rootScope) { if ($rootScope.activeCalls == undefined) { $rootScope.activeCalls = 0; } return { request: function (config) { $rootScope.activeCalls += 1; return config; }, requestError: function (rejection) { $rootScope.activeCalls -= 1; return rejection; }, response: function (response) { $rootScope.activeCalls -= 1; return response; }, responseError: function (rejection) { $rootScope.activeCalls -= 1; return rejection; } }; }); }]);

y luego verificar si activeCalls es cero o no en la directiva a través de $ watch.

module.directive(''loadingSpinner'', function ($http) { return { restrict: ''A'', replace: true, template: ''<div class="loader unixloader" data-initialize="loader" data-delay="500"></div>'', link: function (scope, element, attrs) { scope.$watch(''activeCalls'', function (newVal, oldVal) { if (newVal == 0) { $(element).hide(); } else { $(element).show(); } }); } }; });


Puede agregar una condición y luego cambiarla a través del ramoscopio. Antes de su solicitud de ajax, simplemente llame a $ rootScope. $ Emit (''stopLoader'');

angular.module(''directive.loading'', []) .directive(''loading'', [''$http'', ''$rootScope'',function ($http, $rootScope) { return { restrict: ''A'', link: function (scope, elm, attrs) { scope.isNoLoadingForced = false; scope.isLoading = function () { return $http.pendingRequests.length > 0 && scope.isNoLoadingForced; }; $rootScope.$on(''stopLoader'', function(){ scope.isNoLoadingForced = true; }) scope.$watch(scope.isLoading, function (v) { if(v){ elm.show(); }else{ elm.hide(); } }); } }; }]);

Definitivamente esta no es la mejor solución, pero aún así funcionaría.


Aplicación mecanografiada y angular

directiva

((): void=> { "use strict"; angular.module("app").directive("busyindicator", busyIndicator); function busyIndicator($http:ng.IHttpService): ng.IDirective { var directive = <ng.IDirective>{ restrict: "A", link(scope: Scope.IBusyIndicatorScope) { scope.anyRequestInProgress = () => ($http.pendingRequests.length > 0); scope.$watch(scope.anyRequestInProgress, x => { if (x) { scope.canShow = true; } else { scope.canShow = false; } }); } }; return directive; } })();

Alcance

module App.Scope { export interface IBusyIndicatorScope extends angular.IScope { anyRequestInProgress: any; canShow: boolean; } }

Modelo

<div id="activityspinner" ng-show="canShow" class="show" data-busyindicator> </div> CSS #activityspinner { display : none; } #activityspinner.show { display : block; position : fixed; z-index: 100; background-image : url(''data:image/gif;base64,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'') -ms-opacity : 0.4; opacity : 0.4; background-repeat : no-repeat; background-position : center; left : 0; bottom : 0; right : 0; top : 0; }