0

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");

     }
Gowtham S
  • 923
  • 14
  • 39

1 Answers1

2

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'));
     }
 });
Narendra Jadhav
  • 10,052
  • 15
  • 33
  • 44
  • Yeah i understand that extending the pageViewController will work, but viewModel binding will not work if we extend right? .So you mean like set viewmodel like this 'parent: pageVM,' and define the controller by extending from pageViewController. – Gowtham S Jan 10 '18 at 08:49
  • Is there any way to extend from a class which is already created ? , as i have some property on parent ctrler that i need to access, when extend it calling this.getViewModel() returns popupVM instead of pageVM. – Gowtham S Jan 10 '18 at 09:02
  • @GowthamS you can use this `button.up('formpanel').getViewModel()` instead of `this.getViewModel()`. I have updated my answer and [fiddle](https://fiddle.sencha.com/#view/editor&fiddle/2bo9) as well you can check. – Narendra Jadhav Jan 10 '18 at 10:16
  • That's a good idea..thanks for your effort... I'm exploring some generic approach, as i won't hand code these things all the code are generated(including view), so no control over the code. I have to make the proper syntax for it, so that the code generator engine will do its part .... – Gowtham S Jan 10 '18 at 10:42
  • I'm expecting some thing like reusing the parent/page viewModel n viewController for popup's also ? – Gowtham S Jan 10 '18 at 10:50
  • @GowthamS can you please just explain your requirement so I can see solution on basis that ? – Narendra Jadhav Jan 10 '18 at 12:03
  • I have all my data in page(container) vm & ctrler, I have few other containers called popup which are created on demand (added on viewport) and destroyed after closing. So for transferring data between my popup and page i used to create a new view model by setting parent (as i can't initiate a view which has bindings config). Now here comes my problem, data bindings works perfect but not controller. My base controller treats all items similarly and controls enabling and disabling the view items, but i can't handle that in popup as it is not the child of page. – Gowtham S Jan 10 '18 at 16:20
  • So either i have to copy my data from page to popup or i need to add the popup as child of the page container like popup(not sure is it possible or not). So that the page container will take care of the popup as long as popup was removed from page. Since i'm treating the popup container as foreign object it's not working. If my page access an item i will do like this.getView().down('textfield[itemId=txtuser]'); similarly i can't access popup items from page ctrler. – Gowtham S Jan 10 '18 at 16:29