加载数据以mvc形式

时间:2013-03-26 10:24:06

标签: extjs sencha-touch-2

在我的应用程序中,我有一个列表和详细信息(表单)。我想在单击列表项时将数据加载到详细信息视图(将数据设置为表单的文本字段)。对于列表和详细信息,我从远程服务器获取数据。我正在关注MVC。

现在,当点击listItem时,我可以从服务器获取数据并将其保存到商店并显示详细信息视图。但我无法将数据从商店绑定到文本域。

模型

Ext.define('App.model.Details', {
    extend: 'Ext.data.Model',
    config: {
        fields: [
            {name: 'Name',  type: 'string'},
            {name: 'BillingStreet',  type: 'string'},
            {name: 'BillingCity',  type: 'string'}

        ]
    }
});

存储

Ext.define('App.store.Details', {
    extend: 'Ext.data.Store',
    config: {
        model: 'App.model.Details',
        autoLoad :true,

        grouper : function(record) {
            return record.get('Name')[0];
        },
    }
});

列表视图

Ext.define('App.view.View', {
    extend: 'Ext.List',
    alias:'widget.contactlist',
    fullscreen: true,
    id: 'contactlist',
    config:{
        disableSelection:true,
        store:'Contacts',
        itemTpl:'{Name}',
        items:[
        {
            xtype:'toolbar',
            docked:'top',
            title:'Leeds List'
        }

        ]
    }
});

详情视图

Ext.define("App.view.ListDetail", {
    extend: "Ext.form.Panel",
    requires: "Ext.form.FieldSet",
    alias: "widget.listDetail",
    config:{
        scrollable:'vertical'
    },
    initialize: function () {

        this.callParent(arguments);



        var topToolbar = {
            xtype: "toolbar",
            docked: "top",
            title: "Details"

        };


        this.add([
                  topToolbar,
                  { xtype: "fieldset",
                      items: [{
                          xtype: 'textfield',
                          store: 'Details',
                          value : 'Name',
                          label: 'Name'
                      },
                      {
                          xtype: 'emailfield',
                          store: 'Details',
                          value : 'BillingStreet',
                          label: 'Email'
                      },
                      {
                          xtype: 'passwordfield',
                          store: 'Details',
                          value : 'BillingCity',
                          label: 'Password'
                      }

                      ]
                  }
              ]);


    }

});

控制器

Ext.define('App.controller.Main', {

    extend: 'Ext.app.Controller',

       config: {
        refs: {
            // We're going to lookup our views by xtype.
            contactlist: "contactlist",
            contactdetail: "listDetail",
            //f_name:"#f_name"


        },
        control: {
            contactlist: {
                // The commands fired by the notes list container.
                itemtap: "oneditLeadCommand"

            }

        },

        routes: {
            'contactlist': 'activateList'
        }
    },

    activateList: function ()
    {
        Ext.Viewport.animateActiveItem(this.getContactlist(), this.slideRightTransition);
    },

    slideLeftTransition: { type: 'slide', direction: 'left' },
    slideRightTransition: { type: 'slide', direction: 'right' },

    oneditLeadCommand: function (list, index, target, record, e, eOpts)
    {

        console.log("onEditLead"+record.data.Id);
        this.activateLeadDetail(record);


    },

    activateLeadDetail: function (record)
    {

      var contactDetail = this.getContactdetail();
      //console.log("activateLeadDetail"+contactDetail.textfield);
      //contactDetail.setRecord(record); // load() is deprecated.
      //this.getF_name().setDisplayField("");


      store = Ext.StoreMgr.get('Details');
      //console.log("activateLeadDetail"+store);
      store.setProxy({
        type: 'ajax',
        url : 'http://10.0.2.2:8080/SalesForce/leads/get-lead-details/00D90000000jvoU!AR4AQB6Xcjz4UNBKf12WOcYHWc31QxK2.fXTcbCvOq.oBosCrjBezhqm8Nqc1hrf8MKK5LjLAu8ZC5IqB1kdpWvJGLdWd5pJ/'+record.data.Id,  //  the json file that holds all our contact info.
        reader: {
            type: 'json'
           }
       });
      store.load();
      var record1 = Ext.StoreMgr.get('Details').getAt(0);
      console.log("activateLeadDetail"+record1);

      Ext.StoreMgr.get('Details').each(function(test){
            console.log("for loop"+test.data);
        });
      contactDetail.setRecord(record1);
      Ext.Viewport.animateActiveItem(contactDetail, this.slideLeftTransition);
   },
    // Base Class functions.
    launch: function () {
        this.callParent(arguments);

        console.log("launch");
    },
    init: function () {
        this.callParent(arguments);
        console.log("init");
    }
})

请帮助将数据绑定到详细信息视图。

2 个答案:

答案 0 :(得分:4)

所以我猜你的联系人商店是在其他地方定义的,但由于这个工作正常,你没有在这里粘贴代码。

关于模型的一个快速说明,你应该总是定义一个idProperty。这就是Sencha在内部使用来定义商店中的“主键”,因此在您重新加载/刷新商店时可以正常工作。

Ext.define('App.model.Details', {
    extend: 'Ext.data.Model',
    config: {
        idProperty: 'Name', // Or something from your server maybe?
        fields: [
            {name: 'Name',  type: 'string'},
            {name: 'BillingStreet',  type: 'string'},
            {name: 'BillingCity',  type: 'string'}

        ]
    }
});

其次,当您在listView中使用config方法时,为什么在ListDetail视图中使用initialize方法?如果您指定配置,您将能够通过执行类似

之类的操作以更简单的方式重用其中一些组件
items: [
    {
        xtype: 'ListDetail',
        anyOtherAttribute: value
    }
]

但这有点超出范围。但无论如何。所以我认为这是错误的,你已经为面板的每个字段定义了一个商店。对不起,我无法测试我的假设,但这就是我要做的事情:

Ext.define("App.view.ListDetail", {
    extend: "Ext.form.Panel",
    requires: "Ext.form.FieldSet",
    alias: "widget.listDetail",
    config:{
        scrollable:'vertical'
        items:[
           {
               xtype: "toolbar",
               docked: "top",
               title: "Details"
           },
           { 
                xtype: "fieldset",
                itemId: 'detailedListFiledset', //Overall, prefer itemId
                items: [
                    {
                         xtype: 'textfield',
                         value : 'Name',
                         label: 'Name' // may be you want placeholders here?
                    },
                    {
                         xtype: 'emailfield',
                         value : 'BillingStreet',
                         label: 'Email' // and here..
                    },
                    {
                         xtype: 'passwordfield',
                         value : 'BillingCity',
                         label: 'Password' // and here..
                     }

                  ]
             }
        ]
    }
});

好的,现在问题似乎出现在您的控制器中:

  • 为您的字段集添加引用
  • 添加对商店的引用
  • 在您的商店加载时创建一个afterload回调(详情)
  • 每次清除商店或附加数据并应用于过滤器以获取正确的记录(这就是idProperty非常有用的原因)
  • 设置字段集的记录,不是面板

我没有机会尝试,但我会在今晚稍后再做。但是git it a go。

- 编辑 -

好的,我终于为你编写代码了。

您的代码中存在一些问题。我真的不知道为什么你需要两家商店,但是我们说你这么做了。我将给你我使用的所有文件(两个商店,两个模型,三个视图和控制器)。您的代码中有三个主要问题:

  • 您不应该加载第二个商店并尝试立即获取记录。使用和'加载'或'刷新'事件
  • 表单的SetValues是正确使用的函数
  • 您在表单中缺少name属性,以便表单知道要绑定到字段的商店/模型的值。

ContactModel:

Ext.define('App.model.Contact', {
    extend: 'Ext.data.Model',
    config: {
        idProperty: 'id',
        fields: [
            {name: 'id', type: 'int'},
            {name: 'name',  type: 'string'}
        ]
    }
});

ContactStore的:

Ext.define('App.store.ContactStore', {
    extend: 'Ext.data.Store',
    requires:['App.model.Contact'],
    config: {
        storeId: 'ContactStore',
        model: 'App.model.Contact',
        autoLoad :true,
        data: [
            {id: 0, name: 'Foo'},
            {id: 1, name: 'Bar'}
        ]
    }
});

DetailModel:

Ext.define('App.model.Detail', {
    extend: 'Ext.data.Model',
    config: {
        idProperty: 'id',
        fields: [
            {name: 'id', type: 'int'},
            {name: 'name',  type: 'string'},
            {name: 'billingStreet',  type: 'string'},
            {name: 'billingCity',  type: 'string'}
        ]
    }
});

DetailStore:

Ext.define('App.store.DetailStore', {
    extend: 'Ext.data.Store',
    config: {
        model: 'App.model.Detail',
        autoLoad :true,
        data: [
            {id: 0, name: 'Foo', billingStreet:'here', billingCity: 'Somewhere'},
            {id: 1, name: 'Bar', billingStreet:'there', billingCity: 'Somewhere else'}
        ]
    }
});

ContactView:

Ext.define('App.view.ContactList', {
    extend: 'Ext.List',
    xtype: 'contactList',
    fullscreen: true,

    config: {
        itemId: 'contactList',
        store:'ContactStore',
        emptyText: 'test',
        itemTpl: new Ext.XTemplate(
            '{name}'
        ),
        items:[
            {
                xtype:'toolbar',
                docked:'top',
                title:'Leeds List'
            }
        ]
    }
});

的DetailView:

Ext.define('App.view.Detail', {
    extend: 'Ext.form.Panel',
    requires: ['Ext.form.FieldSet'],
    xtype: "detail",
    config:{
        scrollable:'vertical',
        items: [
          {
            xtype: 'toolbar',
            docked: 'top',
            title: 'Details'
          },
          { 
            xtype: 'fieldset',
            itemId: 'detailForm',
            items: [{
                xtype: 'textfield',
                store: 'Details',
                name: 'name',
                placeHolder : 'Name',
                label: 'Name'
              },
              {
                xtype: 'textfield',
                store: 'Details',
                placeHolder : 'BillingStreet',
                name: 'billingStreet',
                label: 'BillingStreet'
              },
              {
                xtype: 'textfield',
                store: 'Details',
                placeHolder : 'BillingCity',
                name: 'billingCity',
                label: 'BillingCity'
              }
            ]
          }
        ]
    }
});

主要观点:

Ext.define('App.view.Main', {
    extend: 'Ext.Container',
    xtype: 'main',
    config: {
        layout: 'hbox',
        items: [
            {
                xtype: 'contactList',
                flex:1
            },
            {
                xtype: 'detail',
                flex:2.5
            }
        ]
    }
});

主控制器:

Ext.define('App.controller.Main', {
    extend : 'Ext.app.Controller',
    requires: [
        'Ext.Toolbar',
        'Ext.List',
        'App.store.ContactStore',
        'App.store.DetailStore',
        'App.view.Detail',
        'App.view.ContactList'
    ],
    config: {
        //@private
        detailStore: null,
        currentListIndex: -1,
        views : [
            'App.view.ContactList',
            'App.view.Detail'
        ],
        refs: {
            list: 'contactList',
            detail: 'detail',
            detailForm: 'detail #detailForm'
        },
        control: {
            list: {
                itemtap: 'handleItemTapList'
            }
        }
    },
    launch: function() {
        var store = Ext.getStore('DetailStore');
        store.on('refresh', 'handleDetailStoreLoad', this);
        this.setDetailStore(store);
    },
    handleItemTapList: function(list, index, target, record) {
        this.setCurrentListIndex(index);
        this.getDetailStore().load();
    },
    handleDetailStoreLoad: function (store) {
        debugger;
        var record = store.getAt(this.getCurrentListIndex());
        this.getDetail().setValues(record.data);
    }

});

我们可以争论一些事情,但我试图直截了当地让它发挥作用。如果您有更多问题请咨询,但这个例子对我有用。在我看来,您可能不需要第二个商店,因为联系人详细信息可以嵌套在COntact商店中,您可以使用商店的hasMany属性。

答案 1 :(得分:1)

使用form.setRecord()将记录加载到表单

确保您的表单元素具有与模型名称属性匹配的名称属性值

因为你有一个商店,你必须得到一个模型的引用加载,使用说getAt()或find()方法来获取或找到你的商店中的模型