Extjs - How to invoke parent view controller methods from child view controller?

3.4k Views Asked by At

I added a listener onParentPagePopupCommit for button in popup which was declared in parent view controller and added the popup in view port, now the view model bindings are working as expected, but not sure how to invoke the parent view controller methods without exposing the same methods names in child view controller. Is there any way to extend View Controller during runtime in ExtJs Modern 6.5.

Fiddle

onShowChildPopup: function (sender) {
         var popup = sender.up('panel').popups['childPopup'],
             pageCtrler = sender.lookupController(),
             pageVM = pageCtrler.getViewModel(),
             page = pageCtrler.getView(),
             popupCtrler = new Ext.app.ViewController({
                 parent: pageCtrler, //setting parent ctrler
                 //popup commit event on popup view controller
                 onPopupCommit: function () {
                     debugger;
                     Ext.Msg.alert("Popup Update", "Popup View Controller Invoked")
                     console.log("popup view controller - commit");
                 },

                 // this works but any other way
                 // same methods name on popup view ctrler...
                 /*onParentPagePopupCommit: function(){
                     debugger;
                     // I don't like this way of invoking a parent method
                     // this may introduce few more bugs if the parent gets value from its own
                     // view model - (this will be parent vm and not child/popup.)
                     // need something similar to extend inorder to reuse certain methods..
                     this.parent.onParentPagePopupCommit();

                     var vm = this.getViewModel().get('vm');
                     vm.set('fullName',this.getFullName());


                 }*/
             }),
             popupVM = new Ext.app.ViewModel({
                 parent: pageVM, //setting parent view model
                 links: {
                     //vm is not merging with parent
                     //vm: {

                     childvm: {
                         reference: 'ChildModel',
                         create: {
                             address: "child Address",
                             phone: "child Phone"
                         }
                     }
                 }
             });

         popup.controller = popupCtrler;
         popup.viewModel = popupVM;

         popup = Ext.create(popup);
         popup.setShowAnimation({
             type: 'slideIn',
             duration: 325,
             direction: 'up'
         });
         popup.setHideAnimation({
             type: 'slideOut',
             duration: 325,
             direction: 'down'
         });
         popup.setCentered(true);
         /* popup.on('show', function () {
              debugger;
          });*/
         Ext.Viewport.add(popup).show();
         //popup.showBy(page, "c-c");

     }
1

There are 1 best solutions below

8
On

For this you need to use extend config in controller.

For example:

Ext.define('Person', {
    say: function(text) { alert(text); }
});

Ext.define('Developer', {
    extend: 'Person',
    say: function(text) { this.callParent(["print "+text]); }
});

In this FIDDLE, I have created a demo using your code and made some modification. I hope this will help or guide your to achieve you requirement.

Code Snippet

 Ext.define('ParentModel', {
     extend: 'Ext.data.Model',
     alias: 'model.parentmodel',
     fields: [{
         name: 'firstName',
         type: 'string'
     }, {
         name: 'lastName',
         type: 'string'
     }, {
         name: 'address',
         type: 'string'
     }]
 });

 Ext.define('ChildModel', {
     extend: 'Ext.data.Model',
     alias: 'model.childmodel',
     fields: [{
         name: 'address',
         type: 'string'
     }, {
         name: 'phone',
         type: 'number'
     }, {
         name: 'fullName',
         type: 'string'
     }]
 });

 Ext.define('PageViewModel', {
     extend: 'Ext.app.ViewModel',
     alias: 'viewmodel.pageviewmodel',
     links: {
         vm: {
             reference: 'ParentModel',
             create: {
                 firstName: 'firstName-ParentVM',
                 lastName: 'lastName-ParentVM'
             }
         }
     }
 });

 Ext.define('PageViewController', {
     extend: 'Ext.app.ViewController',
     alias: 'controller.pageviewcontroller',

     init: function () {
         this.callParent(arguments);
     },

     //i understand fullname can also be done on model using formula/conver
     //this is just a sample
     getFullName: function () {
         var vm = this.getViewModel().get('vm');
         return vm.get('firstName') + " " + vm.get('lastName');
     },

     //popup commit event on parent view controller
     onParentPagePopupCommit: function (button) {
         var vm = button.up('formpanel').getViewModel().get('vm');
         vm.commit();
         Ext.Msg.alert("Parent Page Update", "Parent View Controller Invoked");
         console.log("Page view controller - commit");
     },

     onShowChildPopup: function (button) {
         var popup = button.up('panel').popups['childPopup'],
             pageCtrler = button.lookupController(),
             pageVM = pageCtrler.getViewModel(),
             page = pageCtrler.getView(),
             popupVM = new Ext.app.ViewModel({
                 parent: pageVM, //setting parent ViewModel
                 links: {
                     //vm is not merging with parent
                     //vm: {
                     childvm: {
                         reference: 'ChildModel',
                         create: {
                             address: "child Address",
                             phone: "child Phone"
                         }
                     }
                 }
             });

         popup.viewModel = popupVM;
         popup = Ext.create(popup);
         popup.setShowAnimation({
             type: 'slideIn',
             duration: 325,
             direction: 'up'
         }).setHideAnimation({
             type: 'slideOut',
             duration: 325,
             direction: 'down'
         }).setCentered(true);
         Ext.Viewport.add(popup).show();
     }
 });

 //Need to extend popup controller from PageViewController(parent)
 Ext.define('PopupViewController', {
     extend: 'PageViewController',
     alias: 'controller.popupviewcontroller',
     //popup commit event on popup view controller
     onPopupCommit: function () {
         Ext.Msg.alert("Popup Update", "Popup View Controller Invoked")
         console.log("popup view controller - commit");
     }
 });

 Ext.define('MainPage', {
     extend: 'Ext.Panel',
     config: {
         title: 'Page',
         width: '100%',
         height: '100%',
         layout: {
             type: 'vbox',
             align: 'stretch'
         }
     },
     viewModel: {
         type: 'pageviewmodel'
     },
     controller: {
         type: 'pageviewcontroller'
     },
     width: '100%',
     height: '100%',
     popups: {
         childPopup: {
             xtype: 'formpanel',
             controller: 'popupviewcontroller',
             title: 'Cild Popup',
             floating: true,
             modal: true,
             hideonMaskTap: true,
             layout: 'float',
             minWidth: 300,
             maxHeight: 580,
             tools: [{
                 type: 'close',
                 handler: function () {
                     var me = this.up('formpanel');
                     me.hide();
                 }
             }],
             items: [{
                 xtype: 'container',
                 layout: {
                     type: 'vbox',
                     align: 'stretch',
                     pack: 'center'
                 },
                 items: [{
                     xtype: 'fieldset',
                     items: [{
                         xtype: 'label',
                         bind: {
                             html: '{vm.firstName} {vm.lastName}'
                         }

                     }, {
                         xtype: 'textfield',
                         label: 'First Name',
                         name: 'firstName',
                         bind: {
                             value: '{vm.firstName}'
                         }
                     }, {
                         xtype: 'textfield',
                         label: 'Last Name',
                         name: 'lastName',
                         bind: {
                             value: '{vm.lastName}'
                         }
                     }, {
                         xtype: 'textfield',
                         label: 'Last Name',
                         name: 'lastName',
                         bind: {
                             //value: '{vm.address}'
                             value: '{childvm.address}'
                         }
                     }]
                 }, {
                     xtype: 'container',
                     docked: 'bottom',
                     layout: 'hbox',
                     items: [{
                         xtype: 'button',
                         text: 'Popup Update',
                         handler: 'onPopupCommit'
                     }, {
                         xtype: 'button',
                         text: 'Parent Update',
                         handler: 'onParentPagePopupCommit'
                     }]
                 }]
             }]
         }
     },
     bodyPadding: 10,
     items: [{
         xtype: 'fieldset',
         title: 'Enter your name',
         items: [{
             xtype: 'textfield',
             label: 'First Name',
             name: 'firstName',
             bind: {
                 value: '{vm.firstName}'
             }
         }, {
             xtype: 'textfield',
             label: 'Last Name',
             name: 'lastName',
             bind: {
                 value: '{vm.lastName}'
             }
         }]
     }, {
         xtype: 'button',
         text: 'Show Popup',
         handler: 'onShowChildPopup'
     }]
 });

 Ext.application({
     name: 'Fiddle',
     launch: function () {
         Ext.Viewport.add(Ext.create('MainPage'));
     }
 });