Results 1 to 5 of 5

Thread: Instance level item listener not skipping component

    Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Sencha User
    Join Date
    Mar 2011
    Location
    Arvada, CO
    Posts
    404

    Default Instance level item listener not skipping component

    I was reading the Declarative Listeners documentation (from this thread's answer), and I'm very confused about something. The documentation states:
    On the other hand, instance-level listeners skip the component and resolve to a ViewController upward in the hierarchy starting with the parent Container.
    With the example of:
    Code:
    Ext.define('MyApp.view.main.Main', {
      extend: 'Ext.container.Container',
      controller: 'main',
      items: [
        {
          xtype: 'user',
          listeners: {
            remove: 'onUserRemove'
          }
        }
      ]
    });
    
    Ext.define('MyApp.view.main.MainController', {
      extend: 'Ext.app.ViewController',
      alias: 'controller.main',
      onUserRemove: function() {
        console.log('user removed');
      }
    });
    Which tells me that the user class has its own controller, but the listeners attached to it (in the Main View class) will be resolved to the Main View's Controller. Great, that makes sense. However, what doesn't make sense is if you add items to this class, and one of these items has a listener on it... this listener apparently tries to resolve to the class's controller.

    Here's an example. I have a SearchPanel class that has a ViewModel and a ViewController. The ViewController controls things like pressing the Search button and any other logic I'd desire for this class. Now, because my SearchPanel is a sort of "base" class that I'll be using across my app, I can't define its items, as they'll vary from view to view. So when I go to define my items in the instance-level config, I'm going to have listeners for some of these items. Unfortunately, it looks like these listeners try to resolve to the SearchPanel class, which is not what I want... I want them to resolve to the ViewController for the defined class.

    In my example, I would like Textfield's listener to resolve to MyView's controller. ou'll notice if you type in the textfield, there will be an error in the console. Is this a bug, or is this by design? If it's by design, how can I get this to work?


  2. #2
    Sencha Premium User evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    19,258

    Default

    Is this a bug, or is this by design?
    Neither, I think, more of a limitation of the system.

    My first thought is that changing the rules of how items lookup their VC scope could do more harm than good, since it could make things confusing for developers. The current system is fairly straightforward (you resolve to your owner controller). The caveat surrounding events on the class body vs on the instance was necessary because it's a fairly common pattern. I can certainly see the use case for what you're trying to achieve, but it's probably a lot less common.

    It would also require extra parsing to find the items that need to fire events upward. For example say your textfield was a complicated container structure. Does that mean everything underneath there all needs to fire up to the parent VC?

    Another thought is that a view with a controller is meant to be a self contained piece that comes as a unit. Because you're pushing on extra working parts, it is somewhat violating that principle because the listener is poking in from an "outside" level.
    Twitter - @evantrimboli
    Former Sencha framework engineer, available for consulting.
    As of 2017-09-22 I am not employed by Sencha, all subsequent posts are my own and do not represent Sencha in any way.

  3. #3
    Sencha User
    Join Date
    Mar 2011
    Location
    Arvada, CO
    Posts
    404

    Default

    Quote Originally Posted by evant View Post
    My first thought is that changing the rules of how items lookup their VC scope could do more harm than good, since it could make things confusing for developers. The current system is fairly straightforward (you resolve to your owner controller). The caveat surrounding events on the class body vs on the instance was necessary because it's a fairly common pattern. I can certainly see the use case for what you're trying to achieve, but it's probably a lot less common.

    It would also require extra parsing to find the items that need to fire events upward. For example say your textfield was a complicated container structure. Does that mean everything underneath there all needs to fire up to the parent VC?
    Ah, so this now becomes an architectural question. I figured straightforward would be that there's a simple rule... wherever the handler is defined, it's looked up in that class's ViewController. Meaning for my example, onChangeTextField is in MyViewController. If I wanted the handler in the mySearchPanel, I would've put it there, so because I did not, and using the fact that mySearchPanel's instance-level handlers are defined in MyViewController, then that makes logical sense... not this sort of, well, the mySearchPanel's listeners CAN be in MyViewController, but the item definitions cannot, even though we know mySearchPanel has been defined elsewhere (without these items in its view), and it doesn't make sense to just have handlers hanging out in its ViewController without the view having something hook up to these handlers.

    Or at the very least, you allow the dev's to decide what the scope is, like you alluded to in the thread I linked. I figured it wouldn't be that much processing since it seems like the framework knows how to discern an instance level configuration, but I'm also not an author of the framework, so I believe you.

    Sorry, didn't mean to wall of text you there... I enjoy discussions like this, and I always like hearing why things were done the way they were.

    Quote Originally Posted by evant View Post
    Another thought is that a view with a controller is meant to be a self contained piece that comes as a unit. Because you're pushing on extra working parts, it is somewhat violating that principle because the listener is poking in from an "outside" level.
    Alright, so if that's the case, how would you handle this type of situation? Would I assign a reference in MyView, and then in MyViewController's init just add the listener?

  4. #4
    Ext JS Premium Member
    Join Date
    May 2008
    Location
    Austria, Vienna
    Posts
    265

    Question

    If hit the same problem with a view that combines several other views each with their own viewcontroller.
    According to the section 'Resolving Scope to ViewControllers' in the linked blog the scope resolution should work as incutonez and I have thought it would: a listener defined in a view resolves to this views' controller even if the view class has its own viewcontroller, at least that's exactly what the second example shows:
    MyApp.view.user.User has a controller
    MyApp.view.main.Main uses it with xtype: 'user' and adds a listener 'remove' which names function 'onUserRemove' is looked up in the main controller rather than in the user controller.

    Maybe this should work and I've hit a bug as the listener which resolves incorrect isn't on the component itself but its selModel:

    All unrelated config options removed:
    Code:
    Ext.define('NAC.view.scaninterface.NewPanel', {
      extend: 'Ext.container.Container',
    
    
      controller: 'scaninterfacenewpanel',
    
    
      items: [{
        xtype: 'nacformgrid',
        selModel: {
          selType: 'checkboxmodel',
          mode: 'SINGLE',
          listeners: {
            selectionchange: 'onNewInterfaceSelectionChange'
          }
        }]
    });
    onNewInterfaceSelectionChange is searched in the nacformgrids' controller rather than in the scaninterfacenewpanel controller.

    Is this a bug?

  5. #5
    Ext JS Premium Member
    Join Date
    May 2008
    Location
    Austria, Vienna
    Posts
    265

    Lightbulb

    Reading http://docs.sencha.com/extjs/6.0.2-c..._encapsulation again it looks like it should work to include another view which has its own controller and still make event listeners trigger functions on the parent viewcontroller.

    And indeed that works! You just have to define the listener on the grid itself in my case instead of its selection model:

    Code:
    Ext.define('NAC.view.scaninterface.NewPanel', {
      extend: 'Ext.container.Container',
      controller: 'scaninterfacenewpanel',
      items: [{
        xtype: 'nacformgrid',
        listeners: {
          selectionchange: 'onNewInterfaceSelectionChange'
        },
        selModel: {
          selType: 'checkboxmodel',      mode: 'SINGLE'
        }]
    });

Similar Threads

  1. Replies: 1
    Last Post: 24 Apr 2014, 4:33 PM
  2. Replies: 1
    Last Post: 15 Oct 2013, 2:29 AM
  3. Is there any Mechanism in Ext to Recognize which level the component in?
    By eingmarra in forum Ext 2.x: Help & Discussion
    Replies: 4
    Last Post: 11 Feb 2008, 2:02 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •