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>