Директива машинописного текста AngularJS

Возникли проблемы с созданием вложенной директивы с помощью Typescript. Я могу сделать это на простом AngularJ: 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 для загрузки скрипта.


person Algimantas Krasauskas    schedule 30.07.2013    source источник
comment
Я предполагаю, что вы регистрируете их. Смотрите мой обновленный ответ :)   -  person basarat    schedule 31.07.2013


Ответы (4)


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

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';    
    }
}

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

Используйте классы для вашего контроллера. Контроллеры внутри директив также вызываются с помощью оператора new. То же, что и контроллеры снаружи: http://www.youtube.com/watch?v=WdtVn_8K17E Снова пусть поможет машинописный текст. вы со значением this внутри определения контроллера. Кроме того, вы можете использовать type для контроллера в дочерней директиве примерно так (для безопасности типов и вывода):

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

Для внедрения в директивные функции я все еще использую $inject. У меня есть следующее определение интерфейса:

interface Function{
    $inject:string[]
}

Это означает, что вы можете сделать:

foo.$inject = ['$compile']; // e.g
person basarat    schedule 30.07.2013
comment
То, как я использую директиву, позволяет мне использовать инъекцию, и я возвращаю объект при вызове функции, поэтому помещение его в функцию заставит меня вводить Injectables в другое место, где я определяю директиву. И это решение по-прежнему не работает, если содержимое страницы берется из кеша. - person Algimantas Krasauskas; 30.07.2013
comment
добавлено примечание о внедрении в функции :) - person basarat; 31.07.2013
comment
При регистрации директивы первая буква идентификатора строки ДОЛЖНА БЫТЬ СТРОЧНОЙ. Это заставило меня немного застрять, думая, что я мог бы следовать соглашению С#, надеюсь, это кому-то поможет. - person parliament; 27.01.2014
comment
@parliament следует соглашению js в html;). Причина PS: html нечувствителен к регистру => директива 'fooBar' используется как 'foo-bar', и поэтому 'Foo' нельзя использовать, поскольку '-foo' сам по себе странен - person basarat; 27.01.2014

Проблема связана не с 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;
    }
} 
person Algimantas Krasauskas    schedule 31.07.2013
comment
Как добавить директиву, объявленную таким образом, в модуль Angular? - person Trevor; 01.04.2015

С моим решением вы можете использовать класс 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>
person Johannes    schedule 25.09.2015
comment
Этот пример работает с $location, но не работает с $scope. Я получаю Unknown provider: $scopeProvider <- $scope <- myDirective - person Pakman; 28.10.2015
comment
Чтобы исправить это, я зарегистрировал свой контроллер в своем модуле директив и указал controller: 'MyDirectiveController' в своей директиве. - person Pakman; 28.10.2015
comment
На самом деле, вот еще лучший метод (прокрутите вниз до директив/to-do-list.ts) - person Pakman; 02.11.2015

простой способ написать директиву в 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>
person Whisher    schedule 03.09.2013