EXTJS中同一按钮的一个视图和多个控制器操作

时间:2012-09-10 11:13:28

标签: extjs4 extjs extjs-mvc

我的EXTJS应用程序中有一个删除按钮。点击按钮,打开确认表,询问用户是否确定要删除该项。删除按钮是我的应用程序中许多表单的一部分。无论使用何种形式,我都会打开确认窗口。

点击确认窗口中的“是”按钮,我想做一些动作。但是这些操作必须特定于首先打开的表单。所以,我对如何使用相同的视图,相同的按钮,但根据打开的第一个表单使用不同的操作感到困惑。

查看:这是在单击任何表单中的删除按钮时打开的窗口

  Ext.define('app.view.GenMessageWin', {
extend : 'Ext.panel.Panel',
alias : 'widget.genmessagewin',

  var fp = {
        xtype : 'panel',
        itemId : 'MSGPANEL',
        width : Width,
        height : 150,
        cls : 'msg effect1',
        layout : 'form',
        border : false,
        items : [{
            xtype : 'panel',
            //cls : 'winTitle',
            html : msgTxt,
            border : 0
        }, {
            xtype : 'form',
            itemId : 'MSGFORM',
            border : false,
            title : '',
            buttonAlign : 'center',
            fieldDefaults : {
                msgTarget : 'side',
                labelWidth : 110,
                size : 30
            },

            buttons : [{
                text : LANG.BTYES,
                iconCls : 'icon-tick-tb',
                iconAlign : 'right',
                cls : 'tip-btn',
                action : 'delete',
                id : 'BTYES'
            }, {
                text : LANG.BTNO,
                iconCls : 'icon-cross-tb',
                iconAlign : 'right',
                cls : 'tip-btn',
                action : 'notDelete',
                id : 'BTNO'
            } ]

控制器

        init : function() {

         this.control({

        'button[action = delete]' : {
            click : this.delete
        },
        'button[action = notDelete]' : {
            click : this.notDelete
        },

因此,在删除操作中,我们必须首先确定哪个表单已打开,然后相应地删除数据。

4 个答案:

答案 0 :(得分:2)

您有3个选项:

1)使选择器更具体:

'form1 button[action=delete]': {
    click: this.form1Delete
},

form1Delete: function(){
    this.showMsg(function() {
        // form 1 delete
    });
}

2)遍历组件层次结构并找到打开的表单

onDelete: function(btn) {
    var form = btn.up('form'); // find an xtype form or subclass
    if (form.someCondition) {
       //foo
    } else {
        //bar
    }
}

3)正如德米特里所说。你需要将它转换为'MVC风格'。

Ext.define('ConfirmButton', {
    extend: 'Ext.button.Button',

    title: '',
    msg: '',

    requires: ['Ext.window.MessageBox'],

    initComponent: function(){
        this.callParent();
        this.on('click', this.handleClick, this);
    },

    handleClick: function(){
        Ext.MessageBox.confirm(this.title, this.msg, this.checkResponse, this);
    },

    checkResponse: function(btn){
        if (btn == 'yes') {
            this.fireEvent('confirm', this);
        }
    }
});

Ext.onReady(function(){

    var btn = new ConfirmButton({
        renderTo: document.body,
        text: 'Foo',
        title: 'Should I',
        msg: 'Are you sure'
    });

    btn.on('confirm', function(){
        console.log('Do something');
    })

});

答案 1 :(得分:1)

我正在做类似的事情;我只是使用原生的Ext.Msg类

控制器代码

,onDelete: function() {
    var me = this;
    Ext.Msg.show({
        title:'Really shure?',
        msg: 'Really wanna do this?',
        buttons: Ext.Msg.YESNO,
        icon: Ext.Msg.QUESTION,
        closable: false,
        fn: function(btn) {
            if (btn == 'yes') {
                me.deleteRecord();
            }
        },
        scope: me
    });
}
,deleteRecord: function() {
    var me = this,
        store = Ext.StoreMgr.lookup('datastore');
    store.remove(me.selectedRecord);
    store.sync();
}

我建议你在控制器内保留所有关于此的逻辑。我是你的情况,看起来没问题,因为你只是抓住按钮事件。如果您使用完全相同的窗口,那么问题可能是所有控制器都会捕获这些。

您可以通过在创建窗口时动态创建action属性值来解决此问题。与action='onDeleteCar'

一样

答案 2 :(得分:1)

我认为你应该嵌入确认'按钮内部的功能,即创建自己的ConfirmButton类,只有当对话框退出时,才会在按下并执行传递的处理程序时触发对话框。是的"。

以下是示例实现:

Ext.define('My.ConfirmButton',  {
    extend: 'Ext.button.Button',
    alias: 'widget.confirmbutton',

    dlgConf: {
        title: 'Are you sure?',
        msg: 'Are you sure you want to delete this?',
        buttons: Ext.Msg.YESNO,
        closable: false
    },

    initComponent: function() {
        this.callParent(arguments);
        // remember the originally passed handler
        this.origHandler = this.handler;
        this.origScrope = this.scope;

        // override current handler to fire confirmation box first
        this.handler = this.confirmHandler;
        this.scope = this;
    },

    confirmHandler: function(me, e) {
        // show dialog and call the original handler only on 'yes'
        Ext.Msg.show(Ext.applyIf({
            fn: function(buttonId) {
                if(buttonId == 'yes') {
                    me.origHandler && me.origHandler.call(me.origScope || me, me, e)
                }
            },
            scope: me
        }, this.dlgConf))
    },

    // Method used to dynamically reassign button handler
    setHandler: function(handler, scope) {
        // remember the originally passed handler
        this.origHandler = this.handler;
        this.origScrope = this.scope;

        // override current handler to fire confirmation box first
        this.handler = this.confirmHandler;
        this.scope = this;

        return this;
    },
});

以下是示例用法:

Ext.create('My.ConfirmButton', {
    text: 'Delete me',
    renderTo: Ext.getBody(),
    handler: function() {
        alert('Aww, you deleted something! :(')
    }
});

如您所见,确认逻辑对外界是隐藏的,您使用此按钮的方式与使用常规Ext.Button(通过将handler传递给它)完全相同。此外,您可以覆盖按钮触发的对话框的配置(您可能希望根据需要调整它,例如允许将记录名称传递给对话框以获得更友好的UI)。

请注意,代码未经过彻底测试,有些情况可能未被发现。

UPD。您需要将alias(以前的xtype)添加到组件类定义中,以便在控制器代码中的ComponentQuery中使用它,例如。

this.control({
    'confirmbutton[action = delete]' : {
        click : this.delete
    },
    'confirmbutton[action = notDelete]' : {
        click : this.notDelete
    }
})

答案 3 :(得分:0)

我使用的最终解决方案是使用全局命名空间声明变量,以便可以从任何地方访问它们。在打开第一个表单时,我使用记录变量从表单中获取数据,并为它们分配一个全局名称,如

App1.Var1 = record.data.id;

并且,在打开删除窗口时,单击按钮时,App1.Var1可以访问这些变量。