2016-05-13 5 views
1

Aus irgendeinem Grund werden die zugehörigen Ansichten nicht aktualisiert, wenn ich den Factory-Wert aktualisiere. Ich bin an ein Objekt im Service gebunden, nicht an eine Zeichenfolge, also sehe ich nicht, was ich falsch gemacht habe, aber es stimmt definitiv etwas nicht mit der Implementierung. Ich habe den Code für die Kürze reduziert und es zu einem Plünderer hinzugefügt. Ich dachte, ich hätte mit dem Service zu tun, aber anscheinend nicht. Ich las diese article noch einmal, um sicherzustellen, dass das, was ich zu verstehen glaubte, korrekt war.AngularJS 1.5.x Service nicht korrekt gebunden und wird in Controllern nicht aktualisiert

Der Wert des Titels wird zum ersten Mal angezeigt und Sie sehen "Willkommen!" im Titel, aber danach wird es nicht auf "Up Next!"

https://plnkr.co/edit/ma1SDJyIKoFPWznXdxTO?p=preview

<!DOCTYPE html> 
<html ng-app="app"> 
<head> 
    <html-title></html-title> 
</head> 
<body> 

<main></main> 

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script> 

<script> 

(function() { 

    'use strict'; 

    function MainController(HtmlTitleFactory) { 

     HtmlTitleFactory.set('Welcome!'); // title gets set 

     // check title was changed 
     this.data = HtmlTitleFactory.get(); 

     setTimeout(function() { 
      // updates title 
      HtmlTitleFactory.set('Up Next!'); 

      // title looks to be set, but changes not picked up in view 
      console.log(HtmlTitleFactory.get()); 
     }, 3000); 
    } 

    MainController.$inject = [ 
     'HtmlTitleFactory' 
    ]; 

    var main = { 
     template: '<div>{{ vm.data.title }}</div>', 
     controller: MainController, 
     controllerAs: 'vm' 
    }; 

    //////////////////////////// 

    function HtmlTitleController(HtmlTitleFactory) { 

     var vm = this; 

     //vm.title = HtmlTitleFactory.get().title; 
     vm.title = HtmlTitleFactory.get(); 
    } 

    HtmlTitleController.$inject = [ 
     'HtmlTitleFactory' 
    ]; 

    var htmlTitle = { 
     template: '<title>{{ vm.title.title }}</title>', 
     controller: HtmlTitleController, 
     controllerAs: 'vm' 
    }; 

    //////////////////////////// 

    function HtmlTitleFactory() { 

     var service = { 
      title: 'Default' 
     }; 

     function set(title) { 
      // originally tried this since bound to object this should work 
      // service.title = title; 

      // wasn't working so tried this as well 
      angular.extend(service, { 
       title: title 
      }); 
     } 

     function get() { 
      return service; 
     } 

     return { 
      set: set, 
      get: get 
     }; 
    } 

    HtmlTitleFactory.$inject = []; 

    //////////////////////////// 

    angular 
     .module('app', []) 
     .component('main', main) 
     .component('htmlTitle', htmlTitle) 
     .factory('HtmlTitleFactory', HtmlTitleFactory); 

})(); 

</script> 

</body> 
</html> 

Antwort

1

setTimeout ist Ereignis, das Winkel nicht zulassen würde sagen, dass Veränderungen in dem Winkel Kontext als benutzerdefiniertes Ereignis, das außerhalb läuft Winkel Zusammenhang aufgetreten sind. In diesem Fall wird der Digest-Zyklus nicht ausgelöst, Sie müssen ihn manuell ausführen.

Idealerweise sollten Sie $timeout verwenden, das ähnlich funktioniert wie setTimeout und es führt einen Digest-Zyklus aus, wenn der Rückruf ausgelöst wird.

$timeout(function() { 
    HtmlTitleFactory.set('Up Next!'); // update title 
    console.log(HtmlTitleFactory.get()); // title looks to be set but not picked up in view 
}, 3000); 

Plunkr

+0

Und das ist Grund für eine Änderung zu machen, die AngularJS nicht bewusst ist, hat so aufgetreten, wenn ich setTimeout verwendet (die ich nicht), aber wenn ich es täte würde ich brauche ein laufen $ verdauen um es aufzuheben? – mtpultz

+0

@mtpultz Ja, Sie könnten '$ apply()/$ digest()' verwenden, aber das wäre ein schlechtes zu implementierendes Muster, wo Sie erneut die Bedingung hinzufügen müssen, um zu überprüfen, dass der Digest-Zyklus nicht ausgeführt werden soll –

Verwandte Themen