web-dev-qa-db-de.com

$ (document) .bereite Alternative für AngularJS

Ich verwende eine Vorlage namens Gentelella und versuche, AngularJS darin zu implementieren. Ich habe jedoch ein Problem mit einer bestimmten Javascript-Datei. Am Ende dieser Datei wird eine $(document).ready-Funktion aufgerufen, die den Javascript-Code initialisiert, der einige Änderungen im HTML-Code vornimmt. Das Problem ist, dass die Funktion $(document).ready zu früh aufgerufen wird, bevor der HTML-Code vollständig geladen ist. 

Dieses Problem tritt wahrscheinlich auf, weil ich ngRoute verwende und die HTML-Vorlagendatei in die NG-Ansicht der index.html injiziert. In diesem Fall kündigt das DOM wahrscheinlich bereits ein Dokument an, bevor AngularJS die Vorlage (= HTML) eingefügt hat.

Im Grunde muss ich nur einen Weg finden, um Code in einer Javascript-Datei aufzurufen, nachdem AngularJS die Vorlage eingefügt hat.

Ich habe etwas Code angehängt, um einen Einblick in das Problem zu bekommen:

Ausschnitt der custom.min.js

$(document).ready(function () {
  init_sparklines(), init_flot_chart(), init_sidebar(), init_wysiwyg(), init_InputMask(), ...
});

Ausschnitt aus der main.js:

.config(function($routeProvider, $httpProvider) {

  $routeProvider.when('/', {
    templateUrl : 'dash.html',
    controller : 'dash',
    controllerAs: 'controller'
  }).when('/login', {
    templateUrl : 'login.html',
    controller : 'navigation',
    controllerAs: 'controller'
  }).when('/plain_page', {
    templateUrl : 'plain_page.html',
    controller : 'dash',
    controllerAs: 'controller'
  }).otherwise('/');

  $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';

})

Danke im Voraus!

3
Jérémy

Viele jQuery-Plugins hängen von einem Workflow von 1. Zeichnen Sie das DOM ab. 2. Führen Sie eine init()-Funktion aus, um den Code für diese DOM-Elemente festzulegen. 

Dieser Workflow ist in Angular nicht günstig, da das DOM nicht statisch ist: Angular erstellt und zerstört DOM-Knoten im eigenen Lebenszyklus, wodurch Ereignisbindungen oder DOM-Änderungen außerhalb von Angular überschrieben werden können. Document Ready ist nicht besonders nützlich, wenn Sie Angular verwenden, da alles darauf hinweist, dass Angular selbst startbereit ist. 

Um Angular effektiv zu verwenden, müssen Sie sich daran gewöhnen, Code nur dann einzugeben, wenn er tatsächlich benötigt wird. Anstelle eines großen Eimers init_foo(); init_bar(); auf document.ready sollten Sie also eine Foo-Direktive mit eigenem Init-Code und eine Bar-Direktive mit eigenem Init-Code usw. haben. Jede dieser Direktiven sollte nur das DOM ändern, das von dieser spezifischen Direktive erstellt wird. Dies ist die einzige sichere Methode, um sicherzustellen, dass die DOM-Elemente, die Sie ändern müssen, tatsächlich vorhanden sind und dass Sie keine Konflikte oder unerwarteten Abhängigkeiten zwischen Anweisungen erstellen.

Um ein Beispiel zu nennen: Ich schätze, Ihre init_flot_chart() durchsucht das DOM nach einem bestimmten Element, in dem ein Flot-Diagramm gezeichnet wird. Erstellen Sie anstelle dieses Top-Down-Ansatzes eine Direktive:

angular.module('yourApp')
  .directive('flotWrapper', function () {
    return {
      template: "<div></div>",
      scope: {
        data: '@'
      },
      link: function(scope, elem, attrs) {
        var options = {}; // or could pass this in as an attribute if desired
        $.plot(elem, scope.data, options); // <-- this calls flot on the directive's element; no DOM crawling necessary
      }
    };
});

was du so benutzt:

<flot-wrapper data="{{theChartData}}"></flot-wrapper>

... wobei theChartData ein Objekt ist, das die Daten enthält, die im Diagramm gezeichnet werden sollen. (Sie können weitere Attribute hinzufügen, um beliebige andere Parameter zu übergeben, z. B. Flot-Optionen, einen Titel usw.) 

Wenn Angular diese flotWrapper-Direktive zeichnet, erstellt sie zunächst das DOM-Element bzw. die DOM-Elemente in der Direktionsvorlage und führt dann alles, was sich in ihrer link-Funktion befindet, gegen das Stammelement der Vorlage aus. (Die Flot-Bibliothek selbst kann über ein einfaches <script>-Tag eingebunden werden, sodass ihre plot-Funktion verfügbar ist, wenn die Direktive dies benötigt.)

(Beachten Sie, dass dies nicht automatisch aktualisiert wird, wenn sich der Inhalt von theChartData ändert. Ein ausführlicheres Beispiel, das auch auf Änderungen achtet und entsprechend reagiert, ist hier .)

4
Daniel Beck

Wenn Sie ngRoute verwenden, wird Ihr Controller ausgeführt, sobald die Seite geladen wird. Sie können eine init()-Methode aufrufen, wenn der Controller mit dem beginnt, was Sie möchten.

function MyCtrl($scope) {
    function init() {
        console.log('controller started!');
    }
    init();
}

Als Randbemerkung ist dies eine bewährte Methode, die in John Papa Angulars Leitfaden empfohlen wird.


Eine andere Möglichkeit ist die Verwendung der ng-init Direktive, zum Beispiel:

<div ng-controller="MyCtrl" ng-init="myFunction()">...</div>
1
Mistalis

In der letzten Version von angle.js gibt es einen Lebenszyklus-Hook namens $postLink(), der aufgerufen wird, nachdem das Element dieses Controllers und seine untergeordneten Elemente verknüpft wurden. Ähnlich wie die Post-Link-Funktion kann dieser Hook verwendet werden, um DOM-Ereignishandler einzurichten und direkte DOM-Manipulationen durchzuführen. Überprüfen Sie die guide

0
B.Ma