Typescript + Angular "controller as" Sidewaffle 模板开箱即用
Typescript + Angular "controller as" Sidewaffle template doesn't work out of the box
请原谅我后面的代码墙,但每个块只有一个小的变化,每个变化都有注释。
我正在尝试使用 Sidewaffle 模板包附带的 Angular+Typescript "controller as" 模板。这就是开箱即用的模板。我在这里对模板所做的唯一修改是注释、空格以及将 'app1' 重命名为 'app':
interface ItestControllerScope extends ng.IScope {
vm: testController;
}
interface ItestController {
greeting: string;
controllerId: string; //This won't work...
changeGreeting: () => void;
}
class testController implements ItestController {
static controllerId: string = "testController"; //...because this is static.
greeting = "Hello";
constructor(private $scope: ItestControllerScope, private $http: ng.IHttpService, private $resource: ng.resource.IResourceService) {
}
changeGreeting() {
this.greeting = "Bye";
}
}
app.controller(testController.controllerId,
['$scope', '$http', '$resource', ($scope, $http, $resource) =>
new testController($scope, $http, $resource)
]);
首先要注意的是,它甚至不会编译,因为控制器 class 上的静态 controllerId
成员和 controllerId
成员是 Icontroller
界面。由于接口的成员需要在 class 类型的实例端实现,所以这行不通。
这很烦人,但很容易解决,尽管这样做会丢失一些类型检查:
interface ItestControllerScope extends ng.IScope {
vm: testController;
}
interface ItestController {
greeting: string;
changeGreeting: () => void;
}
class testController implements ItestController {
//we leave the static member on the class and remove the member
//from the interface
static controllerId: string = "testController";
greeting = "Hello";
constructor(private $scope: ItestControllerScope, private $http: ng.IHttpService, private $resource: ng.resource.IResourceService) {
}
changeGreeting() {
this.greeting = "Bye";
}
}
app.controller(testController.controllerId,
['$scope', '$http', '$resource', ($scope, $http, $resource) =>
new testController($scope, $http, $resource)
]);
现在可以编译了,但问题是对 app.controller()
的调用如何转换为 javascript。它没有将构造函数直接传递给 app.controller()
,而是包装在一个匿名函数中,我们最终得到的是构造函数中的构造函数:
var testController = (function () {
function testController($scope, $http, $resource) {
this.$scope = $scope;
this.$http = $http;
this.$resource = $resource;
this.greeting = "Hello";
}
testController.prototype.changeGreeting = function () {
this.greeting = "Bye";
};
testController.controllerId = "testController";
return testController;
})();
app.controller(testController.controllerId,
['$scope', '$http', '$resource',
//Why won't this work? Why would we want to do this in the first place?
function ($scope, $http, $resource) {
return new testController($scope, $http, $resource);
}
]);
现在,当我们尝试在视图中使用 "controller as" 语法时,Angular 无法找到别名控制器 - 视图绑定到一个空对象。
据我所知,Typescript 模板应该如下所示:
interface ItestControllerScope extends ng.IScope {
vm: testController;
}
interface ItestController {
greeting: string;
changeGreeting: () => void;
}
class testController implements ItestController {
static controllerId: string = "testController";
greeting = "Hello";
constructor(private $scope: ItestControllerScope, private $http: ng.IHttpService, private $resource: ng.resource.IResourceService) {
}
changeGreeting() {
this.greeting = "Bye";
}
}
//Now we're passing the controller constructor directly instead of
//wrapping the constructor call in another constructor
app.controller(testController.controllerId,
['$scope', '$http', '$resource',testController]);
编译成这个 javascript:
var testController = (function () {
function testController($scope, $http, $resource) {
this.$scope = $scope;
this.$http = $http;
this.$resource = $resource;
this.greeting = "Hello";
}
testController.prototype.changeGreeting = function () {
this.greeting = "Bye";
};
testController.controllerId = "testController";
return testController;
})();
app.controller(testController.controllerId,
['$scope', '$http', '$resource', testController]);
效果很好。所以我有两个主要问题:
- 为什么您想要将控制器构造函数包装在 lambda 中以传递给 Angular 的
controller()
方法而不是直接传递构造函数?
- 为什么模板在 class 上有一个静态成员,它试图用 class 实现的接口上的成员强制执行?
我唯一的猜测是,这两个问题在 Typescript 和 Angular 的某些早期版本组合中都不是问题,但我不知道,因为我对这两个问题都很陌生。我正在使用 Typescript v1.4 和 Angular v1.3.14
Why would you ever want to wrap the controller constructor in a lambda to hand to Angular's controller() method instead of handing over the constructor directly?
你不会。我不 https://www.youtube.com/watch?v=WdtVn_8K17E
Why would the template have a static member on a class that its trying to enforce with a member on the interface that the class implements
关于 controllerId: string; //This won't work...
在接口上拥有一个成员并使用 class 实现该接口意味着 class 的实例将拥有该成员.然而,你想说的是 class 有这个成员。这不能通过 实现接口 来完成。
您可以通过其他方式确保这一点:
var mustHaveId:{controllerId:string};
class Fail{}
class Pass{static controllerId = "Pass"}
mustHaveId = Fail; // Error
mustHaveId = Pass; // Pass
查看 source code on Github 发现有问题的模板是 "updated to be Typescript 1.0 and Angular 1.3 compatible," 因此,结合 Angular 和 Typescript 的先前版本,模板中的所有内容都必须具有过去曾工作过。
我的两个问题在更新的文件中得到了解决,所做的更改与我为获取东西所做的更改相似运行。 Sidewaffle 模板包尚未相应更新。
更新: 在撰写本文时,最新版本的 Sidewaffle 模板包含固定模板。
请原谅我后面的代码墙,但每个块只有一个小的变化,每个变化都有注释。
我正在尝试使用 Sidewaffle 模板包附带的 Angular+Typescript "controller as" 模板。这就是开箱即用的模板。我在这里对模板所做的唯一修改是注释、空格以及将 'app1' 重命名为 'app':
interface ItestControllerScope extends ng.IScope {
vm: testController;
}
interface ItestController {
greeting: string;
controllerId: string; //This won't work...
changeGreeting: () => void;
}
class testController implements ItestController {
static controllerId: string = "testController"; //...because this is static.
greeting = "Hello";
constructor(private $scope: ItestControllerScope, private $http: ng.IHttpService, private $resource: ng.resource.IResourceService) {
}
changeGreeting() {
this.greeting = "Bye";
}
}
app.controller(testController.controllerId,
['$scope', '$http', '$resource', ($scope, $http, $resource) =>
new testController($scope, $http, $resource)
]);
首先要注意的是,它甚至不会编译,因为控制器 class 上的静态 controllerId
成员和 controllerId
成员是 Icontroller
界面。由于接口的成员需要在 class 类型的实例端实现,所以这行不通。
这很烦人,但很容易解决,尽管这样做会丢失一些类型检查:
interface ItestControllerScope extends ng.IScope {
vm: testController;
}
interface ItestController {
greeting: string;
changeGreeting: () => void;
}
class testController implements ItestController {
//we leave the static member on the class and remove the member
//from the interface
static controllerId: string = "testController";
greeting = "Hello";
constructor(private $scope: ItestControllerScope, private $http: ng.IHttpService, private $resource: ng.resource.IResourceService) {
}
changeGreeting() {
this.greeting = "Bye";
}
}
app.controller(testController.controllerId,
['$scope', '$http', '$resource', ($scope, $http, $resource) =>
new testController($scope, $http, $resource)
]);
现在可以编译了,但问题是对 app.controller()
的调用如何转换为 javascript。它没有将构造函数直接传递给 app.controller()
,而是包装在一个匿名函数中,我们最终得到的是构造函数中的构造函数:
var testController = (function () {
function testController($scope, $http, $resource) {
this.$scope = $scope;
this.$http = $http;
this.$resource = $resource;
this.greeting = "Hello";
}
testController.prototype.changeGreeting = function () {
this.greeting = "Bye";
};
testController.controllerId = "testController";
return testController;
})();
app.controller(testController.controllerId,
['$scope', '$http', '$resource',
//Why won't this work? Why would we want to do this in the first place?
function ($scope, $http, $resource) {
return new testController($scope, $http, $resource);
}
]);
现在,当我们尝试在视图中使用 "controller as" 语法时,Angular 无法找到别名控制器 - 视图绑定到一个空对象。
据我所知,Typescript 模板应该如下所示:
interface ItestControllerScope extends ng.IScope {
vm: testController;
}
interface ItestController {
greeting: string;
changeGreeting: () => void;
}
class testController implements ItestController {
static controllerId: string = "testController";
greeting = "Hello";
constructor(private $scope: ItestControllerScope, private $http: ng.IHttpService, private $resource: ng.resource.IResourceService) {
}
changeGreeting() {
this.greeting = "Bye";
}
}
//Now we're passing the controller constructor directly instead of
//wrapping the constructor call in another constructor
app.controller(testController.controllerId,
['$scope', '$http', '$resource',testController]);
编译成这个 javascript:
var testController = (function () {
function testController($scope, $http, $resource) {
this.$scope = $scope;
this.$http = $http;
this.$resource = $resource;
this.greeting = "Hello";
}
testController.prototype.changeGreeting = function () {
this.greeting = "Bye";
};
testController.controllerId = "testController";
return testController;
})();
app.controller(testController.controllerId,
['$scope', '$http', '$resource', testController]);
效果很好。所以我有两个主要问题:
- 为什么您想要将控制器构造函数包装在 lambda 中以传递给 Angular 的
controller()
方法而不是直接传递构造函数? - 为什么模板在 class 上有一个静态成员,它试图用 class 实现的接口上的成员强制执行?
我唯一的猜测是,这两个问题在 Typescript 和 Angular 的某些早期版本组合中都不是问题,但我不知道,因为我对这两个问题都很陌生。我正在使用 Typescript v1.4 和 Angular v1.3.14
Why would you ever want to wrap the controller constructor in a lambda to hand to Angular's controller() method instead of handing over the constructor directly?
你不会。我不 https://www.youtube.com/watch?v=WdtVn_8K17E
Why would the template have a static member on a class that its trying to enforce with a member on the interface that the class implements
关于 controllerId: string; //This won't work...
在接口上拥有一个成员并使用 class 实现该接口意味着 class 的实例将拥有该成员.然而,你想说的是 class 有这个成员。这不能通过 实现接口 来完成。
您可以通过其他方式确保这一点:
var mustHaveId:{controllerId:string};
class Fail{}
class Pass{static controllerId = "Pass"}
mustHaveId = Fail; // Error
mustHaveId = Pass; // Pass
查看 source code on Github 发现有问题的模板是 "updated to be Typescript 1.0 and Angular 1.3 compatible," 因此,结合 Angular 和 Typescript 的先前版本,模板中的所有内容都必须具有过去曾工作过。
我的两个问题在更新的文件中得到了解决,所做的更改与我为获取东西所做的更改相似运行。 Sidewaffle 模板包尚未相应更新。
更新: 在撰写本文时,最新版本的 Sidewaffle 模板包含固定模板。