AngularJS 打字稿指令

Posted

技术标签:

【中文标题】AngularJS 打字稿指令【英文标题】:AngularJS Typescript Directive 【发布时间】:2013-07-30 10:42:25 【问题描述】:

使用 Typescript 创建嵌套指令时遇到问题。我可以用简单的 AngularJs 做到这一点: http://plnkr.co/edit/UruTqEdMnqNT5wjxcQNC?p=preview,

但使用 TypeScript 它给了我 “No controller” 错误消息。

/// <reference path="../../Scripts/AngularJs/Typings/angular.d.ts" />

export class directiveA 
    public static $inject: Array<string> = [];
    constructor() 
        var directive: ng.IDirective = ;
        directive.priority = 0; 
        directive.restrict = "A";
        directive.scope = ;
        directive.transclude = true;
        directive.templateUrl = "otherTemplate.html";
        directive.replace = true;
        directive.controller = function ($scope, $element) 
            this.flip = function () 
                $element.toggleClass("flipped");
             
        
        directive.replace = true;

        return directive;
    
 


export class directiveB
    public static $inject: Array<string> = [];
    constructor() 
        var directive: ng.IDirective = ;
        directive.require = "^directiveA";
        directive.priority = 1;
        directive.restrict = "A";
        directive.scope = 
            simplrSide : "@"
        ;
        directive.transclude = true;
        directive.templateUrl = "templeUrl.html";
        directive.link = function (scope, iElement, iAttrs, simplrEditable) 
            scope.flip = function () 
                simplrEditable.flip();
            
        
        directive.replace = true;
        return directive;
    

我不知道它是否相关,但我正在使用 AMD Require.JS 进行脚本加载

【问题讨论】:

我假设您正在注册这些。查看我的更新答案:) 【参考方案1】:

假设您将这些注册为:

import mod = require('yourfile')
youmodule.directive('directiveA',mod.directiveA);
youmodule.directive('directiveB',mod.directiveB);

只要您的 html 看起来像这样,这应该可以工作:

<div directiveA>
  <div directiveB>
  </div>
</div>

除此之外还有几点注意事项:

为指令定义使用函数。

这是因为指令(与控制器不同)是在没有new 运算符的情况下调用的。所以如果你有类似的东西:

class Test
    foo = "EAC";
    constructor()
        var directive:any = ; 
        directive.restrict = this.foo;
    
 

它编译成不正确 javascript。由于函数 Test 是在没有 new 运算符的情况下调用的,这意味着 this 指的是 window 而不是类的实例。所以无论如何你都不能使用在构造函数之外定义的任何东西。我推荐类似的东西:

function foo():ng.IDirective
    return 
        restrict: 'EAC';    
    

这种方式打字稿将帮助您为 Angular 编写正确的 javascript,而不是以错误的方式指出您。 我会在某个时候制作一个关于这个的视频

为您的控制器使用类 指令中的控制器也使用 new 运算符调用。与外部控制器相同:http://www.youtube.com/watch?v=WdtVn_8K17E 再次让 typescript 帮助您了解控制器定义中 this 的含义。另外,您可以在子指令中将 type 用于控制器,例如(用于类型安全和推理):

link: function (scope, iElement, iAttrs, simplrEditable:YourControllerClass)

用于注入指令函数 我仍然使用 $inject。我有以下接口定义:

interface Function
    $inject:string[]

这意味着你可以这样做:

foo.$inject = ['$compile']; // e.g

【讨论】:

我使用指令的方式让我可以使用注入,并且在调用函数时返回一个对象,因此将其放入函数中会使我在其他地方注入 Injectables,我在其中定义指令.如果页面内容是从缓存中获取的,那么这个解决方案仍然有效。 添加了关于注入函数的注释:) 注册指令时,字符串标识符的首字母必须小写。这让我有点想我可以遵循 C# 约定,希望它对某人有所帮助。 @parliament 在 html 中遵循 js 约定;)。 PS 原因:html 不区分大小写 => 指令 'fooBar' 用作 'foo-bar',因此 'Foo' 不可用,因为 '-foo' 本身很奇怪【参考方案2】:

该问题与 Typescript 无关,而与 AngularJS 指令有关。 将 templateUrl 更改为 template 并使用内联代码有助于解决错误。这是 AngularJS 问题,更多内容:https://github.com/angular/angular.js/issues/1903 希望他们将来能解决这个问题!

export class directiveA 
    public static $inject: Array<string> = [];
    constructor() 
        var directive: ng.IDirective = ;
        directive.priority = 0; 
        directive.restrict = "A";
        directive.scope = ;
        directive.transclude = true;
        directive.template = "<div>Your content</div>";
        directive.replace = true;
        directive.controller = function ($scope, $element) 
            this.flip = function () 
               //Some func
             
        
        directive.replace = true;

        return directive;
    
 

【讨论】:

如何将这样声明的指令添加到 Angular 模块中? this.app.directive("myDirective", () =&gt; new directiveA());【参考方案3】:

使用我的解决方案,您既可以使用 TS 类,又不必担心工厂并重复您需要注入的内容。

module YourApp.Common.Directives 

    class SearchInputController 
        public query: string;

        constructor(private $location: ng.ILocationService) 
        

        doSearch(): void 
            this.$location.url(`/search?q=$this.query`);
            this.query = '';
        
    

    export function SearchInputDirective($location: ng.ILocationService): ng.IDirective 
        return 
            restrict: 'E',
            templateUrl: 'common/directives/searchInput/SearchInputDirective.html',
            replace: true,
            scope: true,
            controllerAs: 'SearchInputController',
            bindToController: 
                'query': '@'
            ,
            controller: (): any => new SearchInputController($location)
        ;
    

    SearchInputDirective.$inject = ['$location'];

注册:

angular.module('common', [])
    .directive('searchInput', YourApp.Common.Directives.SearchInputDirective);

和HTML看全图(templateUrl):

<form ng-submit="SearchInputController.doSearch()">
    <input type="search" ng-model="SearchInputController.query">
</form>

【讨论】:

此示例适用于$location,但适用于$scope。我收到了Unknown provider: $scopeProvider &lt;- $scope &lt;- myDirective 为了解决这个问题,我在我的指令模块中注册了我的控制器并在我的指令中指定了controller: 'MyDirectiveController' 其实这里是an even better method(向下滚动到directives/to-do-list.ts)【参考方案4】:

在ts中编写指令的简单方法 我认为也可以使用嵌套指令

class D
    static foo()
        return 
                restrict:'A',
                template:'<div>Here I am to save the day</div>',
                replace: true
            
    



/// <reference path="./angular.d.ts"/>
/// <reference path="./directive.ts"/>
class MyApp
    public app:AngularModule;
    constructor()
          this.app = angular.module('myApp', []);
          this.app.directive ('superman',() => 
                return D.foo();
             
          );
    

new MyApp();

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Directive</title>
    </head>
    <body>
        <div data-ng-app="myApp">
            <div data-superman></div>  
        </div>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>

    <script src="./directive.js"></script>
    <script src="./appDirective.js"></script>

    </body>
</html>

【讨论】:

以上是关于AngularJS 打字稿指令的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot、maven、AngularJS 2、打字稿和实时重载

如何在没有参考路径的 angularjs 应用程序中使用打字稿定义文件(.d.ts)?

无法在指令 linkFn 中获取控制器引用

Angularjs 类型头指令

找不到角度打字稿打字参考路径

Angular,打字稿更改检测输入文本[重复]