AngularJS Typescript Директива

Наличие проблем с созданием вложенной директивы с использованием 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 для script load

Ответ 1

Проблема не связана с 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;
    }
} 

Ответ 2

Предполагая, что вы регистрируете их как:

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 вызывается без нового оператора, а это означает, что this относится к window, а не к экземпляру класса. Поэтому вы никак не можете использовать что-либо, определенное вне конструктора. Я рекомендую что-то вроде:

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

Этот способ typescript поможет вам написать правильный javascript для angular вместо того, чтобы указывать на то, что вы ошибаетесь. Я сделаю видео об этом в какой-то момент

Использовать классы для вашего контроллера Контроллеры внутри директив также вызываются с новым оператором. То же, что и контроллеры снаружи: 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

Ответ 3

В моем решении вы можете использовать класс TS и не беспокоиться о factory и повторять то, что вам нужно ввести.

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>

Ответ 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>