使用Ext JS访问复杂的REST资源 [英] Accessing complex REST resources with Ext JS

查看:139
本文介绍了使用Ext JS访问复杂的REST资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在访问一个公开这两个资源的REST服务,一个父资源和一个子资源:

I am accessing a REST service which exposes these two resources, a parent resource and a child resource:

/users
/users/{userId}/account

所以资源帐户不嵌套在资源用户,它必须通过第二个请求访问。有这样的REST API的例子,例如此处

So the resource "account" is not nested within the resource "user", it has to be accessed by a second request. There are examples for such REST APIs, e.g. here

我使用这些模型将用户及其帐户映射到Ext Js 4数据模型:

I use these models to map users and their account to the Ext Js 4 data model:

用户

Ext.define("MyApp.model.User", {
    extend: "Ext.data.Model",
    fields: [ { name: "id", type: "string" }],
    associations: [{
            model: "MyApp.model.Account",
            name: "account",
            type: "hasOne",
            reader: "json",
            getterName: "getAccount",
            setterName: "setAccount", 
            foreignKey: "accountId"
        }
    ],
    proxy: {
        type: "rest",
        url: "/rest/users",
        reader: {
            type: "json",
            totalProperty: "total",
            root: "users"
        }
    }
});

帐户

Ext.define("MyApp.model.Account", {
    extend: "Ext.data.Model",
    fields: [ { name: "id", type: "string" }],
    belongsTo: "MyApp.model.User",
    proxy: {
        type: "rest",
        reader: { type: "json"}
    }
});

帐户代理没有url(我希望这将基于父用户模型创建)。当我调用user.getAccount()我得到一个异常,因为代理缺少url。

The account proxy does not have a url (I hoped this would be created based on the parent user model). When I call user.getAccount() I get an exception because the proxy is missing the url.

问题有没有办法设置模型,以便Ext Js可以访问/ users / {userId} / account WITHOUT更新帐户代理网址手动与每个父userId?

推荐答案

你不会得到你想要的股票Ext类,你必须有点脏...

You won't get what you want from stock Ext classes, you'll have to get a little bit dirty...

根据我的理解,你需要用户的id来加载它的帐号,而不是id的帐户记录本身。所以,我将配置关联来反映:

From what I understand you need the id of the user to load its account, not the id of the account record itself. So, I would configure the association to reflect that:

associations: [{
    model: "MyApp.model.Account",
    name: "account",
    type: "hasOne",
    reader: "json",
    getterName: "getAccount",
    setterName: "setAccount",
    // foreignKey: "accountId"
    foreignKey: 'id'
}],

这里的最大优点在于,当被要求构建请求的URL时,用户ID将可用于代理。

The big advantage here being that the user id will be available to the proxy when it will be asked to build the url for the request.

现在,为了使用您需要的格式构建URL,我们必须替换代理的 buildUrl 方法。而且,正如您已经发现的那样,您首先需要一个url来获取此方法。

Now, in order to build the url with the format you need, we must replace the proxy's buildUrl method. And, as you've already discovered, you do need an url to get to this method in the first place.

所以,我将如何配置Account代理:

So, here's how I would configure the Account proxy:

proxy: {
    type: "rest",
    reader: {type: "json"},

    // Give it an URL to avoid the error
    url: '/rest/users/{}/account',

    // Replace the buildUrl method
    buildUrl: function(request) {
        var me        = this,
            operation = request.operation,
            records   = operation.records || [],
            record    = records[0],
            url       = me.getUrl(request),
            id        = record ? record.getId() : operation.id;

        // Here's the part honoring your URL format
        if (me.isValidId(id)) {
            url = url.replace('{}', id);
        } else {
            throw new Error('A valid id is required');
        }

        // That's enough, but we lose the cache buster param (see bellow)
        return url;

        // If we want the cache buster param (_dc=...) to be added,
        // we must call the superclass, which will read the url from
        // the request.
        request.url = url;
        return Ext.data.proxy.Rest.superclass.buildUrl.apply(this, arguments);
    }
}

在这一点上,我们最终得到了代理启动请求表单的URL:

At this point, we end up with the proxy firing request on urls of the form:

rest/users/45/account?id=45

这只是化妆品,但是id查询参数会使我烦恼,所以我也将替换 buildRequest 代理的方法如下:

That's only cosmetic but that id query parameter annoys me, so I would also replace the buildRequest method of the proxy with the following one:

buildRequest: function(operation, callback, scope) {
    var me = this,
        params = operation.params = Ext.apply({}, operation.params, me.extraParams),
        request;

    Ext.applyIf(params, me.getParams(operation));

    // if (operation.id !== undefined && params[me.idParam] === undefined) {
    //     params[me.idParam] = operation.id;
    // }

    request = new Ext.data.Request({
        params   : params,
        action   : operation.action,
        records  : operation.records,
        operation: operation,
        url      : operation.url,
        proxy: me
    });

    request.url = me.buildUrl(request);

    operation.request = request;

    return request;
}

而且,这里你是...虽然它会工作,真的推荐使用这种方式,在代理的配置中。在现实生活中,您应该从其余部分扩展自己的代理类,特别是如果您需要配置许多这样的代理...但是我希望我给你所需要的所有成分开始!

And, here you are... While it would work, I don't really recommend overriding methods this way, in the proxy's config. In real life, you should extend your own proxy class from the Rest one, especially if you need to configure many such proxies... But I hope I gave you all the ingredients you need to get started!

这篇关于使用Ext JS访问复杂的REST资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆