2012-09-21 24 views
18

Estoy trabajando con angularjs y quiero cargar directivas cuando las necesiten, en lugar de cargarlas todas al principio de la página. Estoy intentando crear directivas para mis complementos utilizados con mayor frecuencia.¿Cómo pueden las directivas cargarse en perezoso en angularjs?

De esta manera, uno directo puede usar yepnope para cargar todas las directivas necesarias antes de finalmente compilar el html.

Si la directiva se carga al inicio de la página con los demás, todo funciona bien. Sin embargo, si la directiva 'hijo' se carga más tarde (dentro del 'padre'), no tendrá efecto. A continuación se muestra el código para el campo pre en el campo de compilación de la directiva 'parent'.

... 
    var pre = function (scope, element, attrs) { 
     element.html('Please wait. Loading...'); 
     ang.loadDirectives('caiDatePicker', function() { 
      console.log('loaded'); 
      scope.data.raw = scope.rawData; 
      var html = createObjUi(scope, scope.data, scope.defn); 
      element.html(html); //data 
      $compile(element.contents())(scope.$new()); 
      scope.$apply(); 
     }); 
    }; 
    return { restrict:'A', compile: {pre:pre,post:function(){...}}; 

ang.loadDirectives cargas de la directiva utilizando yepnope. Parte del código para la directiva 'hijo' es el siguiente:

angular.module('mycomponents') //PS: I'm assuming this will fetch the already created module in the 'parent' directive 
.directive('caiDatePicker', function ($parse) { 
    return { 
     scope: {}, 
     restrict: 'A', 
     link: function (scope, element, attrs) { 
      scope.$watch('this.$parent.editing', function (v) { 
       scope.editing = v; 
      }); 
      yepnope({ 
       test: $().datePicker, 
       nope: [ 
        '/content/plugins/datepicker/datepicker.js', //todo: use the loader 
        '/content/plugins/datepicker/datepicker.css' 
       ], 
       complete: function() { 
        if (scope.model && scope.model.value) { 
         var date = scope.model.value; 
         element.val(date.getDate() + '/' + (date.getMonth() + 1) + '/' + date.getFullYear()); 
        } 
        element.datepicker({ weekStart: 1, format: 'dd/mm/yyyy' }) 
         .on('changeDate', function (ev) { 
          scope.model.value = ev.date; 
          scope.$apply(); 
         }); 
       } 
      }); 
      attrs.$observe('path', function (v) { 
       var fn = $parse(v); 
       var model = fn(scope.$parent); 
       scope.model = model; 
      }); 
     } 
    } 
}); 

¿Es lo que estoy haciendo incluso posible en primer lugar?

Si es así, ¿qué estoy haciendo mal?

Respuesta

2

Después de buscar durante tanto tiempo y no obtener ninguna respuesta, que terminó con la siguiente

  1. Crear una aplicación angular. Este es también un módulo angular.
  2. Puede agregar cualquier directiva al módulo en cualquier momento usando app.directive (nombre, función). Estas pueden ser directivas cargadas asincrónicamente.
  3. Puede arrancar cualquier elemento. Cuando arranque, especifique la aplicación en la lista de módulos en angular.

El problema era que yepnope no estaba activando la función completa como yo necesitaba. Al final, construyo una pequeña envoltura encima de yepnope que parece garantizar que se active la función completa.

código final se ve algo como:

var app3 = new Cai.AngApp('app3'); 
app3.loadControllers('app1.controller3', function() { 
     app3.loadDirectives('jsonEditor', 'datePicker', function() { 
      app3.bootstrap($('#d3')); 
    }); 
}); 
+0

enfoque interesante usando bootstrap en el niño. pero esto significa, múltiples bootstraps. ¿Funcionaría? también, ¿podrías explicar lo que hiciste en las ang.loadDirectives? – Lior

+0

para arreglar su problema yepnope puede seguir el primer ejemplo de este comentario: https://github.com/SlexAxton/yepnope.js/issues/91#issuecomment-14526165 – heralight

17

Si desea registrar directivas, después de la aplicación se ha bootstrap, que tendrá que utilizar los $ compileProvider en lugar de la API de módulo. Por ejemplo ...

$compileProvider.directive('SomeLazyDirective', function() 
{ 
    return { 
     restrict: 'A', 
     templateUrl: 'templates/some-lazy-directive.html' 
    } 
}) 

continuación, puede utilizar la función de 'resolver' la hora de definir una ruta con los $ routeProvider para cargar la directiva vago usando su gestor de secuencia de comandos. Para hacer esto, deje que la función devuelva una promesa que se resuelve una vez que su directiva y otras dependencias perezosas se hayan cargado. AngularJS esperará a que se resuelva la promesa antes de presentar la ruta, asegurando así que sus directivas estarán listas antes de que la vista lo necesite. He escrito una publicación en el blog que detalla cómo lograr la carga diferida en AngularJS. Describe con más detalle lo que he indicado aquí y se puede encontrar en http://ify.io/lazy-loading-in-angularjs/

11

Esto es lo que hice, usando el proveedor de compilación asociado a la aplicación, lo que hace que sea accesible desde cualquier lugar donde tenga la referencia del módulo.

 
var app = angular.module('app'); 
app.config(function ($compileProvider) { 
    app.compileProvider = $compileProvider; 
}); 

Luego, más tarde, después de que el bootstrap se puede cargar con pereza una directiva que se compila y vinculado:

 
app.compileProvider.directive('SomeLazyDirective', function() 
{ 
    return { 
     restrict: 'A', 
     templateUrl: 'templates/some-lazy-directive.html' 
    } 
}) 
+1

Esto funcionó para mí, una publicación útil también estuvo aquí: http : //www.codeproject.com/Articles/838402/Lazy-loading-directives-in-AngularJS-the-easy-way –

0

No estoy seguro de cómo el uso de una directiva AngularJS será una respuesta apropiada

He hecho lo siguiente y funciona sin problemas

  • Usa la lista de bigotes para decidir la plantilla del elemento de la lista. (https://github.com/janl/mustache.js/)
  • Al cargar su aplicación apis debería cargar solo 10 -50 registros, dependiendo de su contenido.
  • En el desplazamiento de la lista tan pronto como esté a punto de llegar al final, ejecute el siguiente formulario de llamada de la apis a continuación de los 20 elementos, y así sucesivamente.
  • Si sus datos no cambian, puede almacenarlos localmente y volver a llenarlos.

  • seguir obteniendo los últimos registros y publicitándolo localmente.

Cuestiones relacionadas