Одно представление и несколько действий контроллера для одной и той же кнопки в EXTJS

У меня есть кнопка удаления в моем приложении 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
        },

Итак, в действии удаления мы должны определить, какая форма была открыта в первую очередь, а затем соответствующим образом удалить данные.


person rosebrit3    schedule 10.09.2012    source источник
comment
Можете ли вы объяснить это более четко, пожалуйста:) Я не понимаю вашего объяснения. Прости   -  person rosebrit3    schedule 10.09.2012


Ответы (4)


У вас есть 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');
    })

});
person Evan Trimboli    schedule 10.09.2012

Я делаю что-то подобное; Я просто использую родной класс 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();
}

Я бы порекомендовал вам сохранить всю логику, касающуюся этого, внутри контроллера. В вашем случае кажется, что это не проблема, потому что вы просто ловите события кнопок. Проблема может заключаться в том, что все контроллеры ловят их, если вы используете одно и то же окно.

Вы можете решить эту проблему, например, создав значение свойства действия динамически при создании окна. Как 2_

person sra    schedule 10.09.2012

Я думаю, вам следует встроить функциональность «подтверждения» внутри кнопки, т.е. создать свой собственный класс 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). Кроме того, вы можете переопределить конфигурацию диалогового окна, которое вызывает кнопка (вы можете настроить его в соответствии со своими потребностями, например, разрешить передачу имени записи в диалоговое окно для более удобного пользовательского интерфейса).

Обратите внимание, что код тщательно не тестировался, некоторые случаи могут остаться нераскрытыми.

УПД. Вам нужно добавить alias (бывший xtype) в определение класса компонента, чтобы вы могли использовать его в ComponentQuery в коде вашего контроллера, например.

this.control({
    'confirmbutton[action = delete]' : {
        click : this.delete
    },
    'confirmbutton[action = notDelete]' : {
        click : this.notDelete
    }
})
person Dmitry Pashkevich    schedule 10.09.2012
comment
Можете ли вы объяснить это более четко, пожалуйста:) Я не понимаю вашего объяснения. Прости - person rosebrit3; 10.09.2012
comment
Обновил мой ответ примером. - person Evan Trimboli; 10.09.2012
comment
Смотрите мой обновленный ответ. Просто используйте My.ConfirmButton вместо Ext.Button везде, где вам нужно подтверждение. - person Dmitry Pashkevich; 10.09.2012

Последнее решение, которое я использовал, заключалось в объявлении переменных с использованием глобального пространства имен, чтобы к ним можно было получить доступ из любого места. При открытии первой формы я получаю данные из формы, используя переменную записи, и присваиваю им глобальное имя, например

App1.Var1 = record.data.id;

И при открытии окна удаления эти переменные могут быть доступны App1.Var1 при нажатии кнопок.

person rosebrit3    schedule 19.09.2012