11

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

但使用 TypeScript 它会给我“无控制器”错误消息。

/// <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 进行脚本加载

4

4 回答 4

14

假设您将这些注册为:

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控制器定义内部的含义。另外,您可以在子指令中使用控制器的类型,例如(用于类型安全和推理):

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

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

interface Function{
    $inject:string[]
}

这意味着你可以这样做:

foo.$inject = ['$compile']; // e.g
于 2013-07-30T11:52:52.450 回答
4

该问题与 Typescript 无关,而是与 AngularJS 指令有关。将templateUrl更改为模板并使用内联代码有助于解决错误。这是 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;
    }
} 
于 2013-07-31T10:38:12.020 回答
2

使用我的解决方案,您既可以使用 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>
于 2015-09-25T10:51:11.370 回答
1

我认为在 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>
于 2013-09-03T21:07:19.660 回答