2017-12-19 4 views
3

Ich habe hier ein Problem mit $ Broadcasting-Ereignis zu einem anderen Controller. Also hier ist der Deal. In der Fußzeile der Website habe ich einen anderen Controller geladen (den CMSController). Außerdem habe ich eine Route/Hilfe, wo dieser Controller auch Help Center-Daten von CMS lädt und bekommt. Es gibt Links in der Fußzeile, die damit verbunden sind. Lassen Sie uns den Link "Allgemeine Geschäftsbedingungen" sagen. Um diese Daten zu erhalten, muss ich zur '/ help' route gehen und die getHelpPage() Funktion aufrufen. Das ist die laufende Projektstruktur, an der ich arbeite. Also von Fußzeile I '/ help' Weg bin Umleitung und ein Ereignis sendet, die ich auf theCMSController hören bin und rufen getHelpPage()Ermitteln, wenn der Controller bei der Routenänderung voll geladen ist

$scope.openHelpCenterPage = function openHelpCenterPage(slug) { 
    if($location.path().indexOf('/help') === -1){ 
     $location.path('/help'); 
    } 
     $rootScope.$broadcast('openHelpCenterPage', {slug: slug, from: 'footer'}); 
}; 

Und in der CMSController

$rootScope.$on('openHelpCenterPage', function (event, obj) { 
     $scope.getHelpPage(obj.slug); 
}); 

Das Problem ist, dass dies nicht funktioniert. Ich denke, der CMSController ist nicht geladen, was passiert. Keine Fehler in der Konsole.

jedoch .... Puring die boradcast in $ Timeout löst das Problem auch bei 0 Sekunden ..

$timeout(function() { 
     $rootScope.$broadcast('openHelpCenterPage', {slug: slug, from: 'footer'}); 
    },0); 

Aber ich fühle mich nicht wie ti ist eine gute Lösung. Irgendwelche anderen Ideen ??? Ich habe auch versucht routeChangeSuccess nach dem Hören openHelpCenterPage $ zu hören, aber auch hier keine Ergebnisse ....

$rootScope.$on('openHelpCenterPage', function (event, obj) { 
    $rootScope.$on('$routeChangeSuccess',function(){ 
    $scope.getHelpPage(obj.slug); 
    }) 
}); 

vielleicht andere Möglichkeiten, um herauszufinden, ob Controller vollständig geladen ist ???? Vielen Dank für Ihre Zeit. Hoffe, ich habe das Problem gut erklärt.

+0

versuchen, auf Ereignisse in einem relevanten Bereich mit '$ scope. $ auf (...)' anstelle von '$ rootScope zu hören. $ auf (...) '; ändert sich etwas, wenn Sie '$ emit' anstelle von' $ broadcast' verwenden (für '$ emit' benötigen Sie tatsächlich' $ rootScope. $ on' though)? –

+0

danke für die antwort. Leider funktioniert es nicht so. – Artdark92

Antwort

0

Sie können Ihren CMSController eine der Eigenschaften von rootScope eine nugdge geben lassen, ein Flag setzen. Und Sie können rootScope sagen, dass es nach dem ersten Ereignis alle 100 ms für 1-2 Sekunden überprüft und dann nur dann ein anderes ausstrahlt, wenn das Flag vorhanden ist.

Aber was ich wirklich empfehle, erhalten Sie Vermittlerservice. Machen Sie einfach einen regelmäßigen Dienst, aber verwenden Sie ihn stattdessen, um mit einem Getter und Setter zu einem privaten Objekt zu kommunizieren. Ein Controller setzt das Objekt, ein anderer liest es, wenn es fertig ist. Auf diese Weise wissen Sie, dass der Controller bereit ist, da Sie das Objekt darin anfordern.

angular.module('app') 
    .factory('mediatorService', function() { 
     var _data= {}; 
     return { 
      //setter 
      save: function (data){ 
       _data= data; 
      }, 
      //getter 
      get: function(){ 
       return _data; 
      } 
     } 
}) 

Dann in einem Controller Ihnen:

mediatorService.save(yourobject); 

Und in einem anderen:

$scope.data = mediatorService.get(); 

Für mich ist diese Art und Weise der Kommunikation von Daten zwischen den Controllern dargebotene.Sie haben im Grunde diese Optionen:

  • rootScope als Vermittler schlecht - verpestet rootscope, anderswo missused werden kann, wenn nicht vorsichtig über Namen gut - schnell und fast ohne Code

  • Ereignisse gut - kann an alle, die zuhören, gut, wenn Eltern und Kinder a Re beteiligt schlecht - Synchron Themen wie das Ihre

  • Route params gut - schnell und einfach, wenn Sie verschachtelte bekam Controller schlecht - zeitlich begrenzt über

  • die Verwendung von Cookies und lokaler Speicher gut - wenn Sie beim erneuten Ladenpersistieren müssenschlecht - Workaround außerhalb des Bereichs der eckigen - alte Browser haben nur Cookies. auf Browser-Defending-Einstellungen diejenigen bekommen gelöscht könnten, ohne dass Sie

  • Vermittler serivce gut reagieren zu können - einfach, aber effektiv mit klaren Trennung der Rolle schlecht - erfordert ein wenig mehr Kessel Code

+0

Vielen Dank für die Antwort. Leider habe ich es versucht und es funktioniert auch nicht. Am Ende des Controllers überprüfe ich ob MediatorService.get() ist kein leeres Objekt und Aufruf der GetHelpPage-Funktion, um die Seite zu bekommen ... Aber es funktioniert nicht ... Vielleicht gibt es ein anderes Problem ... – Artdark92

+0

Haben Sie beide Controller in den Dienst injiziert und die Daten in den ersten gesetzt? Vielleicht initialisierst du den 2. Controller vor dem 1. Setup die Daten im Mediator? – DanteTheSmith

+0

Ja, alles ist richtig gemacht. Im ersten Controller setze ich die Daten in Mediator Service. dann check-in der zweiten Controller ... check wird übergeben. Ich bin console.loging das Objekt, es ist definitiv da. Ich übergebe das Objekt in eine Funktion, die die Hilfe-Center-Seite von CMS bekommt ... keine Ergebnisse. Allerdings .... Hier ist eine interessante Sache. Ich habe versucht, es in den $ scope. $$ postDigest() Callback zu wickeln und es hat funktioniert .... Also ich fange an zu denken, dass Controller-Laden ist nicht das Problem .... Digest-Zyklus ist. Ich muss diese Funktion ordnungsgemäß ausführen – Artdark92

0

von meinem Verständnis haben Sie 2 Controller, und wenn Sie versuchen, ein Ereignis von einem zum zweiten Controller zu übertragen, hört es nicht, da es nicht vollständig geladen ist .. dies zu vermeiden Sie können ein Ereignis vom zweiten Controller nach dem Laden auslösen und dann mit normalem Fluss fortfahren werfen Sie einen Blick auf dieses Beispiel. Ctrl2

dies ein Ereignis ausgelöst wird, wenn es

(function() { 

    'use strict'; 

    appName.controller('CMSController', Controller); 
    Controller.$inject = ['$scope', '$rootScope', '$timeout', 'CONSTANTS', '$location', 'PAGE_DATA']; 

    function Controller($scope, $rootScope, $timeout) { 
     function inIt() { 
      $rootScope.$broadcast('pageLoaded'); 
     } 

     inIt(); 
    } 

}()) 

Ctrl1

dies der andere Controller Wetter wird hören geladen wird geladen wird oder nicht dann seine broaddcast auslösen wie diese

(function() { 

    'use strict'; 

    appName.controller('secCtrl', Controller); 
    Controller.$inject = ['$scope', '$rootScope', '$timeout', 'CONSTANTS', '$location', 'PAGE_DATA']; 

    function Controller($scope, $rootScope, $timeout) { 

     var pageload = 0; 
     $rootScope.$on('pageLoaded', function(event, obj) { 
      $rootScope.$broadcast('openHelpCenterPage', {slug: slug, from: 'footer'}); 
     }); 
    } 

}()) 

was ich habe erklären ind ist ein einfacher Ansatz, den Sie von meinem Verständnis versuchen können .try Änderung nach Ihren Anforderungen

+0

danke für die antwort. Das Problem ist, dass zu diesem Zeitpunkt die Strg 2 geladen wird ... Zum Erzeugen der Fußzeilen wird der CMSController verwendet. In dem Moment, in dem ich auf den Fußzeilenlink klicke, wird das 'pageLoaded' Event beim ersten Laden der Seite bereits angezeigt. Das Problem besteht darin, dass der Benutzer beim Klickereignis zu einer anderen Route umgeleitet werden muss, auf der Ctrl2 (CMSController) erneut geladen wird, die GetHelpPages-Funktion jedoch bereits zuvor aufgerufen wurde. – Artdark92

Verwandte Themen