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

查看:25
本文介绍了使用 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,而无需使用每个父 userId 手动更新帐户代理 URL?

推荐答案

你不会从库存中得到你想要的 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 方法.而且,正如您已经发现的,您首先需要一个网址才能访问此方法.

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.

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

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

而且,你在这里......虽然它可以工作,但我真的不建议在代理的配置中以这种方式覆盖方法.在现实生活中,你应该从 Rest 扩展你自己的代理类,特别是如果你需要配置很多这样的代理......但我希望我给了你开始所需的所有要素!

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天全站免登陆