2013-10-17 14 views
13

Ich initialisiere zuerst meine App mit ng-app = "myApp" im body-Tag und das funktioniert gut für alle angularized-html, die beim Laden der ersten Seite geladen wird.Angular bootstrapping nach Laden von html

Später habe ich etwas Code, der angularized-html in das DOM lädt.

In eckigen 1.08 konnte ich gerade angular.bootstrap ($ newLoadHTML, ["myApp"]) nach dem Laden und es würde funktionieren; Dabei ist $ newLoadHTML der neu hinzugefügte HTML-Code, der mit jQuery erfasst wurde.

In Winkel 1.2 dies nicht mehr funktioniert :(

Fehler: [ng: btstrpd] App Bereits Bootstrap mit diesem Element '' http://errors.angularjs.org/1.2.0-rc.2/ng/btstrpd?p0=%3Cdiv%20ng-controller%3D%22AfterCtrl%22%3E

ich diese Störung erhalte, die ich verstehe, aber ich don . ‚t wissen, wie es zu lösen

Was ich tun können müssen, ist Last angularized-html und dann Winkel bewusst machen es

hier ein Plunker ist es zu illustrieren. http://plnkr.co/edit/AHMkqEO4T6LxJvjuiMeT?p=preview

+0

Können Sie das in Fiddle oder Plunker reproduzieren? –

+0

http://docs.angularjs.org/api/angular.bootstrap - Nicht sicher, warum Sie HTML mit jQuery erfassen und dann in eine Angular-Moduldefinition einfügen würden. –

+0

Aktualisierte die Frage. Ich wollte angular.bootstrap schreiben! Es ist eine Legacy-Anwendung, so wie es jetzt funktioniert. Wird später eine Fiddle/Plunker veröffentlichen! – Christian

Antwort

1

Loading an AngularJS controller dynamically

Die Antwort auf diese mein Problem behoben Frage. Da muss ich die Controller erstellen, nachdem der Inhalt zum DOM hinzugefügt wurde. Dieser Fix erfordert, dass ich auch die Controller registriere, nachdem ich sie deklariert habe. Wenn jemand eine einfachere Lösung hat, pleace Chip in.

1

Ihr Ansatz scheint nicht richtig. Sie verwenden jQuery und Angular in einer unangemessenen Weise, die wahrscheinlich Konflikte verursacht.

Angular gebaut ist in Template-Unterstützung ist der beste Weg, dies zu tun, entweder mit ng-schließen oder Sie können Angular des Routing nutzen und zusammen mit ng-Ansicht. Die Dokumentation ist hier:

http://docs.angularjs.org/api/ng.directive:ngInclude

http://docs.angularjs.org/api/ngRoute.directive:ngView

Die einfachste mögliche Sache einfach eingestellt werden würde ng-umfassen, um die URL-Zeichenfolge:

<div ng-include="'ajax.html'"></div> 

Wenn Sie es tatsächlich zu dynamisch laden, wenn Sie etwas tun, dann ist dies eine vollständigere Lösung für Sie:

http://plnkr.co/edit/a9DVEQArS4yzirEQAK8c?p=preview

HTML:

<div ng-controller="InitCtrl"> 
    <p>{{ started }}</p> 
    <button ng-click="loadTemplate()">Load</button> 
    <div class="content" ng-include="template"></div> 
</div> 

Javascript:

var myApp = angular.module('myApp', []) 
.controller('InitCtrl', function($scope) 
{ 
    $scope.started = 'App is started'; 
    $scope.loadTemplate = function() { 
     console.log('loading'); 
     $scope.template = "ajax.html"; 
    } 
}).controller('AfterCtrl', function($scope) 
{ 
    $scope.loaded = 'Is now loaded'; 
}); 
+0

Thx für die Antwort. Das Problem ist, dass es sich um eine Legacy-Anwendung handelt. Daher ist es nicht so einfach, die Struktur zu ändern. Es hat in 1.8 funktioniert, also dachte ich, dass es einen Weg 1.2 auch geben muss – Christian

15

Ich werde wiederholen, was andere schon erwähnt haben: diese Art der Sache ist allgemein eine schlechte Idee, aber ich verstehe auch, dass man manchmal Sie müssen mit Legacy-Code so arbeiten, wie Sie es nicht möchten. Alles in allem können Sie HTML, das von außerhalb von Angular in Angular-gebundene Ansichten geladen wird, mit the $compile service konvertieren. Hier ist, wie Sie vielleicht Ihr aktuelles Beispiel umschreiben, um es mit $compile funktioniert:

// We have to set up controllers ahead of time. 
myApp.controller('AfterCtrl', function($scope) { 
    $scope.loaded = 'Is now loaded'; 
}); 

//loads html and afterwards creates a controller 
$('button').on('click', function() { 
    $.get('ajax.html', function(data) { 

    // Get the $compile service from the app's injector 
    var injector = $('[ng-app]').injector(); 
    var $compile = injector.get('$compile'); 

    // Compile the HTML into a linking function... 
    var linkFn = $compile(data); 
    // ...and link it to the scope we're interested in. 
    // Here we'll use the $rootScope. 
    var $rootScope = injector.get('$rootScope'); 
    var elem = linkFn($rootScope); 
    $('.content').append(elem); 

    // Now that the content has been compiled, linked, 
    // and added to the DOM, we must trigger a digest cycle 
    // on the scope we used in order to update bindings. 
    $rootScope.$digest(); 

    }, 'html'); 
}); 

Hier ist ein Beispiel: http://plnkr.co/edit/mfuyRJFfA2CjIQBW4ikB?p=preview

Es vereinfacht die Dinge ein wenig, wenn Sie Ihre Funktionalität als eine Richtlinie statt roh aufbauen können die Verwendung jQuery - Sie können die Dienste $compile und $rootScope darin einfügen oder sogar den lokalen Bereich innerhalb der Direktive verwenden.Noch besser, wenn Sie dynamische Bindung in ein <ng-include> Element stattdessen verwenden können.

+1

Vielen Dank. Ich habe das noch nicht auf meinem Legacy-Code getestet, aber ich denke, das wird den Job erledigen :-) – Christian

+0

Was ich jetzt im Legacy-Code mache, ist, den HTML-Code zu laden und das Javascript danach auszuführen. Was mit Legacy-Jquery-Code Sinn macht. Da muss das dom eigentlich da sein um es mir zu schnappen. Gibt es trotzdem die Controller nachträglich zu definieren und es trotzdem funktionieren zu lassen! – Christian

+0

Es ist möglich, Controller zu laden, aber Sie müssen ein wenig dafür arbeiten. Sehen Sie sich diesen Artikel an: http://ify.io/lazy-loading-in-angularjs/ –

0

Eine andere gotcha, die zu diesem Bootstrapping-Fehler führt, ist die nginclude oder ngview-Szenarien, in denen Ihre dynamische html Skriptverweise auf angular js enthält.

Meine html unten verursachte dieses Problem, wenn es in eine vorhandene Angular Seite injiziert wurde. Der Verweis auf angular.min.js verursachte einen eckigen zu rebootstrap:

<div id="fuelux-wizard" class="row-fluid" data-target="#step-container"> 
    <ul class="wizard-steps"> 
     <li data-target="#step1"> 
      <span class="step">1</span> 
      <span class="title">Submit</span> 
     </li>  
     <li data-target="#step2"> 
      <span class="step">2</span> 
      <span class="title">Approve</span> 
     </li>  
     <li data-target="#step3"> 
      <span class="step">3</span> 
      <span class="title">Complete</span> 
     </li> 
    </ul> 
</div> 

<script src="/Scripts/Angular/angular.min.js"></script> 
<script type="text/javascript">  
    angular.element('#requestMaster').scope().styleDisplayURL(); 
</script>