使用打字稿的IResourceClass扩展angularjs的$资源

时间:2014-02-10 18:27:27

标签: javascript angularjs typescript

我正在使用Asp.Net Web API和AngularJS开发SPA。我还使用TypeScript来获取静态类型。所以,我添加了DefinitelyTyped angularjs。

因为我正在使用RESTfull服务。我想过使用angularjs的$资源。现在我的资源没有PUT http方法的任何内置方法。所以我决定添加我自己的内容如下。

var employees = $resource('/api/employee/:id',{id:'@id'},{"update":{ method: "PUT", isArray:false }};

现在,正如您所看到的,在普通的AngularJS中很容易做到。我想通过TypeScript路由并定义扩展IResourceClass的自定义接口。这个界面的文档解释如下。

  

//具有默认操作的每个资源的基类。   //如果您为资源定义新操作,则需要   //扩展此接口并将ResourceClass强制转换为它。

我真的无法弄清楚如何扩展这个界面。它不断出现一些关于语法的错误。有人可以解释如何扩展这个接口并添加Update方法,然后在我的控制器上调用PUT方法。

2 个答案:

答案 0 :(得分:29)

首先定义您的模型,即描述您员工的界面。

// Define an interface of the object you want to use, providing it's properties
interface IEmployee extends ng.resource.IResource<IEmployee>
{
    id: number;
    firstName : string;
    lastName : string;
}

然后创建一个描述您将创建的资源的界面。

// Define your resource, adding the signature of the custom actions
interface IEmployeeResource extends ng.resource.IResourceClass<IEmployee>
{
    update(IEmployee) : IEmployee;
}

创建EmployeeResource工厂:

var myApp = angular.module('myApp', ['ngResource']).factory('EmployeeResource', 
    ['$resource', ($resource : ng.resource.IResourceService) : IEmployeeResource => {

        // Define your custom actions here as IActionDescriptor
        var updateAction : ng.resource.IActionDescriptor = {
            method: 'PUT',
            isArray: false
        };

        // Return the resource, include your custom actions
        return <IEmployeeResource> $resource('/api/employee/:id', { id: '@id' }, {
            update: updateAction
        });

    }]);

EmployeeResource注入控制器:

myApp.controller('TestCtrl', ['$scope', 'EmployeeResource', ($scope, Employee : IEmployeeResource) => 
{
    // Get all employees
    var employees : Array<IEmployee> = Employee.query();

    // Get specific employee, and change their last name
    var employee : IEmployee = Employee.get({ id: 123 });
    employee.lastName = 'Smith';
    employee.$save();

    // Custom action
    var updatedEmployee : IEmployee = Employee.update({ id: 100, firstName: "John" });
}]);

创建新的员工实例:

您可以IEmployee new工厂创建EmployeeResource类型的实例。

myApp.controller('TestCtrl', ['$scope', 'EmployeeResource', ($scope, Employee : IEmployeeResource) => 
{
    var myEmployee : IEmployee = new Employee({ firstName: "John", lastName: "Smith"});
    myEmployee.$save();
}

因此,在上面的情况中,我们将IEmployeeResource注入Employee。然后,我们可以new此对象创建IEmployee

答案 1 :(得分:1)

我完全同意斯科特的回答:https://stackoverflow.com/a/21786326/2677975

我还有一个补充: 在我的项目中,我创建了类ServiceModel<T>,它实现了接口IActionDescriptor

module Common.ApiService {
    export class HttpHeaders {
        'Content-Type': string;
        Accept: string;
    }

    export class ServiceModel<T> implements ng.resource.IActionDescriptor {
        public method: string = 'GET';
        public params: T;
        public isArray: boolean = false;
        public url: string;
        public headers: HttpHeaders = new HttpHeaders()
    } 
}

然后,我可以在我的控制器中设置方法,就像Scott一样,但是现在,IDE将在标题上进行类型完成(以及后面的参数)

export interface IProfileServiceResource extends ng.resource.IResourceClass<IProfileDataModelDef> {
    SaveProfileImage(profileImageUri: Profile.Model.UserProfileModel): ng.resource.IResource<Array<any>>;
}

export class ProfileApiService 
    implements Common.ApiService.IApiServiceBase<IProfileServiceResource> {

    public SaveProfileImage: Common.ApiService.ServiceModel<Profile.Model.UserProfileModel>;

    constructor() {    
        this.SaveProfileImage = new Common.ApiService.ServiceModel<Profile.Model.UserProfileModel>();
        this.SaveProfileImage.method = "POST";
        this.SaveProfileImage.url = "/api/Profile/SaveProfileImage";
        this.SaveProfileImage.headers["Content-Type"] = 'application/json';
}

我将此作为补充答案,因为它仅用于为headersparams提供类型。