1. #1
    Sencha User
    Join Date
    Jun 2011
    Posts
    5
    Vote Rating
    0
    spanosyan is on a distinguished road

      0  

    Question Developing a custom PagingToolbar for use with an OpenSearch service

    Developing a custom PagingToolbar for use with an OpenSearch service


    Hi All,

    I'm trying to extend the ext PagingToolbar and ext data store in order to have the store fire an event after data is loaded. This event will cause the paging toolbar to update the service call parameters used when the next and previous buttons are clicked. To do this, I have extended both components and have tried to introduce a custom "changelinks" event that the data store should fire after loading in new data and the paging toolbar should listen for to update itself.

    Since the server side code implements OpenSearch, it returns json data which contain "next" and "previous" link properties. When these two links are present in the json data returned by the server, I want to update the links my custom paging toolbar contains and enable the next and previous buttons accordingly. This essentially implements remote paging, but not using the start and limit parameters because I cannot modify the server-side code to do so.

    After the load event is caught by the data store, it looks at the returned json data for nextLink and prevLink fields and grabs the links. It creates an object with those links and fires a custom event "changelinks" that the paging toolbar should be listening for. When the toolbar catches the event, it will update its links so that when the next and previous buttons are clicked, they submit the correct request.

    I cannot provide a link to the page nor the OpenSearch service that I use because they are behind a great number of company firewalls. I know the search service works since the initial request succeeds and data is loaded into the grid.

    With that said, my first problem is that the toolbar's 'changelinks' event handler is not called, but the event is fired by the data store. Using firebug, I stepped through all function calls after the event was fired, which means at some point it would stop in the changelinks event handler. However, this never happens. How do I define and register the event and its handlers properly? I've already looked at the 3.3.1 API, all available tutorials dealing with event handling and have done quite a bit of searching for problems/solutions similar to this, but to no avail.

    Also, to perform this type of custom paging I need to overwrite the click handlers for the next and previous buttons. It's clear what I've done below isn't the way to handle the click events because none of the info messages get displayed in firebug. What is the proper way to overwrite the PagingToolbar click handlers?

    Thanks in advance for your time and effort!

    Here is the code for the extended classes described above:

    PHP Code:
    CustomPagingToolbar Ext.extend(Ext.PagingToolbar, {
        
    constructor: function (config) {
            
    this.nextLink "";
            
    this.prevLink "";
            
    this.addEvents({
                
    changelinkstrue
            
    });
            
    CustomPagingToolbar.superclass.constructor.call(thisconfig);
        },

        
    listeners: {
            
    click: function (which) {
                switch (
    which) {
                case 
    'next':
                    
    console.log("has next");
                    break;
                case 
    'previous':
                    
    console.info("has previous");
                    break;
                default:
                    
    console.info("delegating click to superclass");
                    
    CustomPagingToolbar.superclass.onClick.call(thiswhich);
                    break;
                }
            },

            
    changelinks: function (params) {
                
    console.info('change caught');

                
    // update nextLink url
                
    if (params.hasNext) {
                    
    this.next.disabled false;
                    
    this.nextLink params.nextLink;
                } else {
                    
    this.next.disabled true;
                }

                
    // update prevLink url
                
    if (params.hasPrev) {
                    
    this.prev.disabled false;
                    
    this.prevLink params.prevLink;
                } else {
                    
    this.prev.disabled true;
                }
            }
        }
    });

    GranuleDataStore Ext.extend(Ext.data.Store, {
        
    constructor: function (config) {
            
    this.addEvents({
                
    changelinkstrue
            
    });
            
    this.enableBubble('changelinks');
            
    GranuleDataStore.superclass.constructor.call(thisconfig);
        },

        
    listeners: {
            
    load: function (storerecordsoptions) {
                
    console.info("results loaded");
                var 
    params = {};

                
    // Grab Next link and add it to the params object
                
    var next store.reader.jsonData.next;
                if (
    next !== "" && next !== undefined) {
                    
    params.hasNext true;
                    
    params.nextLink next;
                    
    console.info(next);
                } else {
                    
    params.hasNext false;
                    
    params.nextLink "";
                }

                
    // Grab previous link and add it to the params object
                
    var prev store.reader.jsonData.prev;
                if (
    prev !== "" && prev !== undefined) {
                    
    params.hasPrev true;
                    
    params.prevLink prev;
                    
    console.info(prev);
                } else {
                    
    params.hasPrev false;
                    
    params.prevLink "";
                }

                
    // Fire the changelinks event 
                
    store.fireEvent('changelinks'params);
            }
        }
    }); 

  2. #2
    Sencha User skirtle's Avatar
    Join Date
    Oct 2010
    Location
    UK
    Posts
    3,338
    Vote Rating
    248
    skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of

      0  

    Default


    No idea about the OpenSearch stuff but I can answer your question about events.

    The changelinks event is being fired on the store whereas your listener is on your CustomPagingToolbar. Your attempt to use enableBubble() is a nice idea but as far as I'm aware it will only bubble events up through the component hierarchy, so it doesn't apply to a store and toolbar.

    Something like this should work...

    Code:
    CustomPagingToolbar = Ext.extend(Ext.PagingToolbar, {
        initComponent: function () {
            CustomPagingToolbar.superclass.initComponent.call(this);
    
            this.nextLink = "";
            this.prevLink = "";
    
            this.store.on('changelinks', this.changeLinksHandler, this);
        },
    
        changeLinksHandler: function (params) {
            ...
        },
    
        listeners: {
            click: function (which) {
                ...
            }
        }
    });

  3. #3
    Sencha User
    Join Date
    Jun 2011
    Posts
    5
    Vote Rating
    0
    spanosyan is on a distinguished road

      0  

    Default


    Thanks Skirtle! I had figured as much when I watched the events bubble up using firebug. Your suggestion fixed the problem with the pagingtoolbar not catching the event. I do have another question regarding the functionality I'm implementing. I'd like to enable the next and previous buttons of the paging toolbar in the handler when I catch the changelinks event. I tried something like:

    Code:
    changeLinksHandler: function(params) {
      if(params !== undefined) {
        if(params.hasNext) {
          this.nextLink = links.nextLink;
          this.next.enable();
        }
      }
    However, the above does not activate the next button on the paging toolbar. It sets the nextLink property correctly though. I can verify this using firebug by making the pagingtoolbar instance I create a global variable or just outputting it to the console. Going through, I can see that the property gets set to the new link passed in through the params object. Now here is the interesting part. For the sake of discussion, suppose I called the global variable pagingBar. Typing pagingBar.next.enable() in firebug enables the button yet this.next.enable() doesn't do so. Is there something I'm missing in order to enable the next and previous buttons through the handler function?

    Thanks!

  4. #4
    Sencha User skirtle's Avatar
    Join Date
    Oct 2010
    Location
    UK
    Posts
    3,338
    Vote Rating
    248
    skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of

      0  

    Default


    Code:
    changeLinksHandler: function(params) {
      if(params !== undefined) {
        if(params.hasNext) {
          this.nextLink = links.nextLink;
          this.next.enable();
        }
      }
    I assume the use of links is a typo and it should be params?

    What you've done looks like it should work so long as this is what you think it is. Try stepping in with a debugger to confirm it is going into enable(). Perhaps something else is kicking in and calling disable() or setDisabled()? Might be worth putting breakpoints on those methods too. (I'd recommend Chrome's debugger for this, I generally find it copes better with large JS files like ext-all-debug.js).

    One thought on improving the code I posted previously, it might be better to use mon() rather than on():

    Code:
    this.mon(this.store, 'changelinks', this.changeLinksHandler, this);
    This will automatically unregister the event handler when the toolbar is destroyed, rather than when the store is destroyed. If the store and toolbar are destroyed at the same time then it shouldn't matter but often stores are more long-lived than UI components and you need to stop them firing events against destroyed UI components.

    A few other suggestions:

    Code:
    if (next !== "" && next !== undefined) {
    I fully approve of your use of triple equals (double equals is evil) but unless you have a good reason not to I'd suggest rewriting this as:

    Code:
    if (next) {
    Likewise I don't see any need for if(params !== undefined) {. The passing of a defined params object should be part of the contract of the changelinks event. Being that defensive isn't in the spirit of good JavaScript, even if it is in other languages.

    I'd also get rid of your params.hasNext and params.hasPrev as they appear to be redundant. Just use params.nextLink and params.prevLink instead.

  5. #5
    Sencha User
    Join Date
    Jun 2011
    Posts
    5
    Vote Rating
    0
    spanosyan is on a distinguished road

      0  

    Thumbs up


    I cleaned up the code as suggested and used breakpoints to follow the load and changelinks events. As it turns out, since the pagingtoolbar class itself listens for the load event fired by the store it is tied to, the calls to enable and disable buttons in the changeLinksHandler function in my extended class are nullified.

    What happens is the load event is fired by the store. Then the store load event handler is called. Within the store's load event handler, the changelinks event is fired. So, the changelinks event gets processed and everything is going as it should. The next and previous buttons get enabled as needed. After the changelinks event is processed, the store's load event handler returns and the pagingtoolbar superclass load handler is called. Here is where the undesired behavior takes place.

    In the pagingtoolbar superclass onLoad function, unless there are multiple pages to display, the handler will disable the first, prev, next, and last buttons. So to prevent that from happening, I had to override the onLoad function in the following manner.

    Code:
    onLoad: function (store, records, options) {
        if (!this.rendered) {
            this.dsLoaded = [store, records, options];
            return;
        }
        var p = this.getParams();
        this.cursor = (options.params && options.params[p.start]) ? options.params[p.start] : 0;
        var d = this.getPageData(),
            ap = d.activePage,
            ps = d.pages;
        this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
        this.inputItem.setValue(ap);
        this.refresh.enable();
    }
    This way, I got the functionality of enabling the buttons at the right time while still allowing the necessary updating of internal variables to be occur. You'll see that its pretty much a replica of the PagingToolbar superclass onLoad function without all the calls to disable/enable buttons.

    All in all this has been a pretty good learning experience and I can't thank you enough for your help and guidance skirtle. Hopefully this discussion ends up helping others as well!

    All the best,

    sp

  6. #6
    Sencha User skirtle's Avatar
    Join Date
    Oct 2010
    Location
    UK
    Posts
    3,338
    Vote Rating
    248
    skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of skirtle has much to be proud of

      0  

    Default


    You might be better off moving all of the logic from your load listener into the onLoad() override instead, it would remove the need for all of that copy and paste code:

    Code:
    onLoad: function(store, records, options) {
        GranuleDataStore.superclass.onLoad.apply(this, arguments);
    
        // other logic from your load listener
    
        this.fireEvent('changelinks', params);
    }
    There are lots of undocumented methods like onLoad() in the framework that have names that sound a bit like events. They're generally to be considered as protected template methods for overriding in circumstances like this. Personally I always try to avoid having a subclass listen to its own events, I'd always favour overriding these template methods instead.

    In changeLinksHandler() you'd then have something like:

    Code:
    this.nextLink = params.nextLink;
    this.next.setDisabled(!this.nextLink);

Thread Participants: 1

Tags for this Thread

film izle

hd film izle

film sitesi

takipci kazanma sitesi

takipci kazanma sitesi

güzel olan herşey

takipci alma sitesi

komik eğlenceli videolar