1

私は以前に同様の質問をしました: https://stackoverflow.com/questions/11707007/nested-json-form-submits-in-extjs4-getting-the-writer-to-remap-the-fields

また、Sencha フォーラムで質問されましたが、かなり絶望的です。

ネストされた json ファイルを関連付けられたモデルに読み書きする際に、多くの問題があります。

私が間違っていることを誰かが見つけてくれることを期待して、ここにできるすべてのコードを書きます。

質問はテキストで強調されています。

私が受け取っているjsonは次のようになり、変更できません: テスト:

[
    {
        "name":"qwerty",
        "id":"1",
        "uid":"1",
        "created":"1341481071",
        "changed":"1343804076",
        "status":"1",
        "jmeterOptions":{
            "jmx":"\/files\/20141\/multi.jmx",
            "engines":"0",
            "version":"2.5.1",
            "consoleArgs":" -t sample.jmx -JDelay=10000 -JEmbedded=1 -JRampup=1800 -JUsers=10",
            "engineArgs":" -JDelay=10000 -JEmbedded=1 -JRampup=1800 -JUsers=10",
            "instanceType":"m1.medium",
            "overrideOptions":{
                "threads":"50",
                "rampUpTime":"300",
                "iterations":"-1",
                "duration":"-1"
            }
        },
        "testOptions":{
            "type":"BM_TEST_TYPE_AUTO",
            "geo":"us-east-1",
            "timeout":"1",
            "reportByEmail":"1",
            "launchTime":"0",
            "sessionId":"",
            "hosts":null,
            "privateIps":null
        },
        "autoOptions":{
            "users":"10",
            "delay":"10",
            "rampUpTime":"1800",
            "pages":[
                {
                    "label":"sencha",
                    "url":"http:\/\/sencha.com"
                }
            ]
        },
        "seleniumOptions":{
            "pages":[
                {
                    "label":"sencha",
                    "url":"http:\/\/sencha.com"
                }
            ]
        }
    },
    {
        "name":"Instant Load test",
        "id":"2",
        "uid":"1",
        "created":"1336921297",
        "changed":"1341132949",
        "status":"1",
        "jmeterOptions":{
            "jmx":null,
            "engines":"0",
            "version":"2.5.1",
            "consoleArgs":" -t sample.jmx -JDelay=10000 -JEmbedded=1 -JRampup=1800 -JUsers=10",
            "engineArgs":" -JDelay=10000 -JEmbedded=1 -JRampup=1800 -JUsers=10",
            "instanceType":"m1.medium",
            "overrideOptions":null
        },
        "testOptions":{
            "type":"BM_TEST_TYPE_AUTO",
            "geo":null,
            "timeout":"1",
            "reportByEmail":"0",
            "launchTime":"0",
            "sessionId":"",
            "hosts":null,
            "privateIps":null
        },
        "autoOptions":{
            "users":"10",
            "delay":"10",
            "rampUpTime":"1800",
            "pages":[
                {
                    "label":"",
                    "url":"http:\/\/cnn.com"
                }
            ]
        },
        "seleniumOptions":{
            "pages":[
                {
                    "label":"",
                    "url":"http:\/\/cnn.com"
                }
            ]
        }
    }
]

モデルは次のようになります。

 Ext.define('BM.model.Test', {
    extend: 'Ext.data.Model',
    fields: [
        {name: 'name', type: 'string'},
        {name: 'id', type: 'id'},
        {name: 'uid', type: 'mumber'},
        {name: 'created', type: 'date', dateFormat: 'timestamp'},
        {name: 'changed', type: 'date', dateFormat: 'timestamp'},
        {name: 'status', type: 'number'},


        {name: 'jmeterJmx', mapping: 'jmeterOptions.jmx', type: 'string'},
        {name: 'jmeterEngines', mapping: 'jmeterOptions.engines', type: 'number'},
        {name: 'jmeterVersion', mapping: 'jmeterOptions.version', type: 'string'},
        {name: 'jmeterConsoleArgs', mapping: 'jmeterOptions.consoleArgs', type: 'string'},
        {name: 'jmeterEngineArgs', mapping: 'jmeterOptions.engineArgs', type: 'string'},
        {name: 'jmeterInstanceType', mapping: 'jmeterOptions.instanceType', type: 'string'},

        {name: 'testOptionsType', mapping: 'testOptions.type', type: 'string'},
        {name: 'testOptionsGeo', mapping: 'testOptions.geo', type: 'string'},
        {name: 'testOptionsTimeout', mapping: 'testOptions.timeout', type: 'number'},
        {name: 'testOptionsReportByEmail', mapping: 'testOptions.reportByEmail', type: 'string'},
        {name: 'testOptionsLaunchTime', mapping: 'testOptions.launchTime', type: 'string'},
        {name: 'testOptionsSessionId', mapping: 'testOptions.sessionId', type: 'string'},
        {name: 'testOptionsHosts', mapping: 'testOptions.hosts', type: 'string'},
        {name: 'testOptionsPrivateIps', mapping: 'testOptions.privateIps', type: 'string'},


        {name: 'autoUsers', mapping: 'autoOptions.users', type: 'number'},
        {name: 'autoDelay', mapping: 'autoOptions.delay', type: 'number'},
        {name: 'autoRampUpTime', mapping: 'autoOptions.rampUpTime', type: 'number'}
    ],


    hasMany: [
        {model: 'Pages', name: 'autoPages', associationKey: 'autoOptions.pages'},
        {model: 'Pages', name: 'seleniumPages', associationKey: 'seleniumOptions.pages'}
    ],


    proxy: {
        type: 'ajax',
        api: {
            read: '../webapp/get/tests',
            update: '../webapp/set/test'
        },
        reader: {
            type: 'json',
            root: 'tests',
            successProperty: 'success'
        },
        writer: new Ext.data.JsonWriter({
            encode: false,
            writeAllFields: true,
            getRecordData: function (record) {
                Ext.apply(record.data,record.getAssociatedData(true));
                return record.getAssociatedData(true);
            }
        })
    }
});


Ext.define('Pages', {
    extend: 'Ext.data.Model',
    fields: [
        {name: 'label', type: 'string'},
        {name: 'url', type: 'string'}
    ]
});

最初の質問:次の 4 行を含めると、グリッドが空で読み込まれます。なぜですか?

{name: 'jmeterOverrideThreads', mapping: 'jmeterOptions.overrideOptions.threads', type: 'number'},
{name: 'jmeterOverrideRampUpTime', mapping: 'jmeterOptions.overrideOptions.rampUpTime', type: 'number'},
{name: 'jmeterOverrideIterations', mapping: 'jmeterOptions.overrideOptions.iterations', type: 'number'},
{name: 'jmeterOverrideDuration', mapping: 'jmeterOptions.overrideOptions.duration', type: 'number'},

2 番目の質問:関連するデータが空になります。rawData には上記のような json がありますが、getAssociatedData で正しいデータを入力するにはどうすればよいですか? いっそのこと、私の関連付けが機能しないのはなぜですか?

3 番目の質問:ライターは空の関連データのみを送信するようになりました。すべてのデータを受信したとおりに送信するにはどうすればよいですか?

これに対する私の解決策は非常に醜いです:

    updateTest: function(button) {
        var form = button.up('panel');
        var record = form.getRecord(),
            values = form.getValues();


        record.set(values);


        var rd = record.data;


//        this.getTestsStore().sync();         //No! Sends flattened data.
//        var autoPages = record.getAssociatedData().autoPages; // Is currently empty
//        var seleniumPages = record.getAssociatedData().seleniumPages; // Is currently empty

        var autoPages = [];
        var seleniumPages = [];
        var iterator = 0;
        var autoPagesLabel = record.data['autoPagesLabel' + iterator];
        var autoPagesUrl = record.data['autoPagesUrl' + iterator];
        while (autoPagesLabel != undefined){
            autoPages.push({
                'label': autoPagesLabel,
                'url': autoPagesUrl
            });
            iterator++;
            autoPagesLabel = record.data['autoPagesLabel' + iterator];
            autoPagesUrl = record.data['autoPagesUrl' + iterator];
        }
        iterator = 0;
        var seleniumPagesLabel = record.data['seleniumPagesLabel' + iterator];
        var seleniumPagesUrl = record.data['seleniumPagesUrl' + iterator];
        while (seleniumPagesLabel != undefined){
            seleniumPages.push({
                'label': seleniumPagesLabel,
                'url': seleniumPagesUrl
            });
            iterator++;
            seleniumPagesLabel = record.data['seleniumPagesLabel' + iterator];
            seleniumPagesUrl = record.data['seleniumPagesUrl' + iterator];
        }



        var reformattedJson = {
            "name": rd.name,
            "id": rd.id,
            "uid": rd.uid,
            "created": rd.created,
            "changed": rd.changed,
            "status": rd.status,
            "jmeterOptions":{
                "jmx": rd.jmeterJmx,
                "engines": rd.jmeterEngines,
                "version": rd.jmeterVersion,
                "consoleArgs": rd.jmeterConsoleArgs,
                "engineArgs": rd.jmeterEngineArgs,
                "instanceType": rd.jmeterInstanceType,
                "overrideOptions": {
                    "threads": rd.jmeterOverrideThreads,
                    "rampUpTime": rd.jmeterOverrideRampUpTime,
                    "iterations": rd.jmeterOverrideIterations,
                    "duration": rd.jmeterOverrideDuration
                }
            },
            "testOptions":{
                "type": rd.testOptionsType,
                "geo": rd.testOptionsGeo,
                "timeout": rd.testOptionsTimeout,
                "reportByEmail": rd.testOptionsReportByEmail,
                "launchTime": rd.testOptionsLaunchTime,
                "sessionId": rd.testOptionsSessionId,
                "hosts": rd.testOptionsHosts,
                "privateIps": rd.testOptionsPrivateIps
            },
            "autoOptions":{
                "users": rd.autoUsers,
                "delay": rd.autoDelay,
                "rampUpTime": rd.autoRampUpTime,
                "pages": autoPages
            },
            "seleniumOptions":{
                "pages":seleniumPages
            }
        };


        Ext.Ajax.request({
            url: '../webapp/set/test',
            method:'Post',
            jsonData: reformattedJson,
            success: function(response){
                var text = response.responseText;
                // process server response here
                console.log('Post successfull!  ');
            }
        });
    }

これは次の形式です。

Ext.define('BM.view.test.Edit', {
    extend: 'Ext.form.Panel',
    alias: 'widget.test-edit',

    layout: 'anchor',
    title: 'Edit Test',
    defaultType: 'textfield',

    items: [
            {name: 'id', hidden: true},
            {name: 'name', fieldLabel: 'Name'},
            {name: 'status', fieldLabel: 'Status'},
            {name: 'testOptionsType', fieldLabel: 'Type'},
            {name: 'autoUsers', fieldLabel: 'User count'}
        ],

     buttons: [
        {
            text: 'Save',
            action: 'save'
        },
        {
            text: 'Cancel',
            scope: this,
            handler: this.close
        }
    ]
});

これがフォームと呼ばれるものです: (グリッド行をクリック)

editTest: function(grid, record) {
    var view = Ext.widget('test-edit');
    var viewPort = Ext.ComponentQuery.query('viewport')[0];

    var autoPages = record.raw.autoOptions.pages;
    var seleniumPages = record.raw.seleniumOptions.pages;
    for (var i =0; i < autoPages.length; i++){
        var tf = Ext.create('Ext.form.field.Text', {
            id: 'autoPagesLabel' + i,
            name: 'autoPagesLabel' + i,
            fieldLabel: 'Label',
            value: autoPages[i].label,
            columnWidth:0.5
        });
        view.add(tf);
        tf = Ext.create('Ext.form.field.Text', {
            id: 'autoPagesUrl' + i,
            name: 'autoPagesUrl' + i,
            fieldLabel: 'Url',
            value: autoPages[i].url,
            columnWidth:0.5
        });
        view.add(tf);
    }


    view.loadRecord(record);
    viewPort.layout.centerRegion.removeAll();
    viewPort.layout.centerRegion.add(view);
}

私は Ext JS 4 の MVC アーキテクチャに従ってみました。

私は何を間違っていますか?

他の情報やコードが必要ですか? 教えてください。投稿します。

4

1 に答える 1

0

私の質問のいくつかに有効な解決策を見つけました。

最初の質問への回避策として、3 つ以上のレベルのマッピングに問題があることがわかったので、hasOne 関係を追加しました。私はそれが良い解決策だとは思いませんが、他に誰もいないので、これについてコメントしてください。

{name: 'jmeterOverrideThreads', mapping: 'jmeterOptions.overrideOptions.threads', type: 'number'},
{name: 'jmeterOverrideRampUpTime', mapping: 'jmeterOptions.overrideOptions.rampUpTime', type: 'number'},
{name: 'jmeterOverrideIterations', mapping: 'jmeterOptions.overrideOptions.iterations', type: 'number'},
{name: 'jmeterOverrideDuration', mapping: 'jmeterOptions.overrideOptions.duration', type: 'number'},

モデルから、次のようになります。

hasOne: [
        {model: 'OverrideOptions', associationKey: 'jmeterOptions', reader: {root: 'overrideOptions'}}
],

// and:

Ext.define('OverrideOptions', {
    extend: 'Ext.data.Model',
    fields: [
        {name: 'jmeterOverrideThreads', mapping: 'threads', type: 'number'},
        {name: 'jmeterOverrideRampUpTime', mapping: 'rampUpTime', type: 'number'},
        {name: 'jmeterOverrideIterations', mapping: 'iterations', type: 'number'},
        {name: 'jmeterOverrideDuration', mapping: 'duration', type: 'number'}
    ]
});

アソシエーションが機能しないという私の2番目の質問については、私のモデルでは、代わりに:

hasMany: [
        {model: 'Pages', name: 'autoPages', associationKey: 'autoOptions.pages'},
        {model: 'Pages', name: 'seleniumPages', associationKey: 'seleniumOptions.pages'}
],

追加した:

hasMany: [
        {model: 'Pages', name: 'autoPages', associationKey: 'autoOptions', reader: {root: 'pages'}},
        {model: 'Pages', name: 'seleniumPages', associationKey: 'seleniumOptions', reader: {root: 'pages'}}
    ],

突然、record.getAssociatedData() から自分のデータにアクセスできるようになりました。まだフラット化されていますが、少なくともデータはあります。

総当たりで行ったように書き込む以外に、ライターにデータを元の形式で出力させることについては、まだ良い考えがありません。それについてのフィードバックをもう一度いただければ幸いです。

他にも疑問が生じました: 関連するデータをフォームに追加したいです。オブジェクトの配列について話しているので、いくつになるかわかりません。元の質問で使用した方法よりも、関連データからフォームを作成するより良い方法はありますか。実行中の反復子でフィールドに名前を付ける以外に、フォームデータにアクセスするより良い方法はありますか: a1、a2、...

ご回答ありがとうございます。

于 2012-08-06T08:56:52.917 に答える