2

Stack: Typoskript 1.7 + Angular 1,49

Zusammenfassung:

ich eine Richtlinie haben. Ich möchte $inject winkel $timeout Service. Es funktioniert gut in der Controller-Funktion der Direktive, aber nicht in der Link-Funktion. Was vermisse ich?

Fragen:

  • Was habe ich falsch gemacht?
  • Gibt es einen besseren Weg zu $inject die $timeout Abhängigkeit?
  • Warum funktioniert der Dienst $timeout im Controller der Direktive, aber nicht im Link?

MyDirective.ts:

module app.directives { 

    export class MyDirective { 
     priority = 0; 
     restrict = 'E'; 
     templateUrl = 'template.html'; 
     scope = { 
      'items': '=' 
     }; 
     controller = MyController; 
     link = MyLink; 

     static $inject = ['$timeout']; 

     constructor(private $timeout:ng.ITimeoutService) { 
     } 
    } 

    function MyController($scope:ng.IScope, $timeout:ng.ITimeoutService) { 
     console.log("controller", $timeout); // function timeout(fn,delay,invokeApply){ the guts here } 
     $timeout(function() { 
      console.log("This works fine"); 
     },3000); 
    } 

    function MyLink(scope:ng.IScope, element:ng.IAugmentedJQuery, attr:ng.IAttributes, $timeout:ng.ITimeoutService) { 
     console.log("link to", $timeout); // MyController {} 
     $timeout(function() { 
      console.log("This throws the error, TypeError: $timeout is not a function"); 
     },3000); 
    } 
} 

Connecting es in directives.ts:

module app.directives { 
    angular.module('app').directive('MyDirective',['$timeout',($timeout:ng.ITimeoutService) => new MyDirective($timeout) ]); 
} 

app.ts

module app { 
    angular.module('app', []); 
} 

Was nicht funktioniert hat:

  • Mit this.$timeout in MyLink mit oder ohne $timeout in den Parametern einschließlich.
  • Ich habe mehrere Artikel und Beispiele gefunden, die ich versucht habe, um sicherzustellen, dass ich die Logik in meiner App befolge, sie aber scheinbar nicht bekomme.

Schlussnoten

  • Typoskript-Angular ist noch neu und es gibt so viele Best Practices, die weit davon entfernt sind definiert. Ein Teil des Projekts meines Teams ist es, einige davon zu finden.
  • Wir haben an dieser allgemeinen Struktur für eine Weile gearbeitet, also, es sei denn, es gibt einen zwingenden Grund, bitte unterlasse Vorschläge, dass ich die Struktur von allem zu sehr ändere.

Antwort

6

Verbindungsfunktionen werden nicht direkt von der Direktiveninstanz ausgeführt, daher erhalten Sie this nicht als Konfigurationsinstanz der Richtlinie (die Sie über den Operator new instanziieren). Außerdem können Sie der Verknüpfungsfunktion (für die der Anweisungskonstruktor bestimmt ist) nichts injizieren. Im Gegensatz zum Controllerkonstruktor werden die Argumente für die Verknüpfungsfunktion automatisch von der Anweisungsausführungslogik übergeben. Sie können einen Pfeiloperator verwenden, um dieses Problem zu beheben.

Beispiel:

export class MyDirective { 
    priority = 0; 
    restrict = 'E'; 
    templateUrl = 'template.html'; 
    scope = { 
     'items': '=' 
    }; 
    controller = MyController; 

    link:ng.IDirectiveLinkFn = (scope:ng.IScope, element:ng.IAugmentedJQuery, attr:ng.IAttributes) => { 

     //Here 
     this.$timeout(function() { 

     },3000); 
    }; 

    constructor(private $timeout:ng.ITimeoutService) { 
    } 
} 

Oder Sie könnten den Kontext mit function.bind binden. d. h. link = MyLink; und Zugang zu $timeout unter Verwendung von this.$timeout.

Wenn interseted Sie könnten einen Blick auf die Schaffung einiger syntaktischer Zucker durch experimentelle Dekoratoren für Richtlinien oder Sie könnten versuchen, etwas zu erkunden like this. Jedoch (nur meine Meinung) scheint eine Klasse für die Direktiven-Konfiguration ein Overkill zu sein, du könntest genauso gut eine Funktion mit statischem Injizieren verwenden.

+0

Gut eins, besser als meins. – kutomer

+0

Danke, das funktioniert! – MaxRocket

1

Link Funktion 4. Parameter ist die Controller Instanz selbst.

Wenn Sie es tun wollen, sollten Sie so etwas wie:

module app.directives { 

    export class MyDirective { 
     link = MyLink; 

     static $inject = ['$timeout']; 

     constructor(public $timeout:ng.ITimeoutService) { 
     } 
    } 

    function MyLink(scope:ng.IScope, element:ng.IAugmentedJQuery, attr:ng.IAttributes, ctrl:any) { 
     ctrl.$timeout(function() { 
      console.log("This throws the error, TypeError: $timeout is not a function"); 
     },3000); 
    } 
} 

Ich weiß, dass dies nicht elegant ist, aber ich habe harte Zeit, eine bessere Lösung zu finden, was denken Sie?

+1

Danke für die Antwort, tho! – MaxRocket