1. #1
    Sencha User CSchmitz81's Avatar
    Join Date
    Nov 2012
    Location
    Saint Louis
    Posts
    33
    Vote Rating
    0
    Answers
    3
    CSchmitz81 is on a distinguished road

      0  

    Default Answered: doLayout does not recalculate the components dynamically added to a container

    Answered: doLayout does not recalculate the components dynamically added to a container


    Hi. I have a method in my controller that gets relative paths from a php file and then takes the resulting list and creates image components for them. When the method fires it adds all of the images in as expected, but at the end i have a .doLayout() method call to have the layout recalculate but it doesn't work.

    I've tried adding in the doLayout at all of the points in the process, even in my loops to create the enclosing containers, and it doesn't work. Once the method is done and the page is built I can manually resize the browser window and all of the images snap to the sizes they should be.

    I've also tried using the method .doComponentLayout() and I've tried hiding the parent container and showing it after the child components are all added and neither of these worked either.

    Can anyone offer up any help? My method looks like this:

    Code:
        getPhotos: function (){
            var photoStore                          = this.getPhotosStore();
            photoStore.proxy.extraParams            = {};
            photoStore.proxy.extraParams.callMethod = "getThumbs";
            var photoContainer                      = this.getPhotoContainer();
    
    
            photoStore.removeAll();
            photoStore.load({
                callback: function (records, operation, success){
                    for (var ct = 0; ct < records.length; ct+=4){
                        // group these into containers of four buttons
                        var row = Ext.create("Ext.container.Container",{
                            layout:{type: 'hbox', pack: 'center'},
                        })
                        // we have to add the items like this b/c if there is no record (if there's not a number of images evenly divisible by four) we'll get an error 
                        for (var innerLoopCt = 0; innerLoopCt < 4; innerLoopCt++ ){
                            if ( ct + innerLoopCt < records.length){
                                row.add(Ext.create("Ext.Img",{src: records[ct + innerLoopCt].data.thumbPath}));
                            }                        
                        }
                        photoContainer.add(row);    
                    }
                    photoContainer.doLayout();
                }
            });
        },

    and the view file that it's being rendered to looks like this:

    Code:
    Ext.define('CaRWedding.view.content.Photos',{
        extend: 'Ext.container.Container',
        xtype: 'photos',
        id: 'photosPanel',
        cls: 'background',
        autoScroll: true,
        layout: {type: 'hbox', pack: 'center'},
        
        config:{
            layout: 'vbox',
            defaults: {flex:1},
            items: [
                {
                    xtype    : 'container',
                    layout   : {type: 'vbox', pack: 'center'},
                    defaults : {flex: 1},
                    id       : 'photoContainer' // this is the container that the controller's photoContainer ref creates the getPhotoContainer method for
                }
            ]
        }
    });

  2. So for anyone who may run into this problem in the future, here's how I solved my problem.

    The setup:
    I have a directory full of image thumbnails of various dimension that I wanted to return to my application. because the dimensions were not all the same I did not want to specify fixed height and widths for the images.

    The php file I built to return the images from the scanned directory returns the relative path from the root of my web server which is then used by the sencha controller to create image components grouped by four into containers. The structure looks like this:
    - Photo Container
    - Row Container
    - Image Component
    - Image Component
    - Image Component
    - Image Component
    - Row Container
    - Image Component
    - ......
    The problem:
    Because I did not specify a fixed width and height for the image components, the images were returned as tiny blocks that did not take their actual size until the window was resized or the page was reloaded without clearing the cache.
    Attachment 42528

    Possible solutions that did not work:
    I tried numerous methods to solve the problem and with each of them the resulting image components rendered the same.
    - Calling a doLayout method from the photo container after the row containers have been added to it as children, tried the same with doContainerLayout
    - Calling a doLayout method from the each row container as they are created, tried the same with doContainerLayout
    - Calling a doLayout and doContainerLayout method after the method for getting the images has been called and finishes
    - Adding a listener to the photo container that performs a doLayout, doContainerLayout, or update method call on render, beforerender, activate, etc (I stopped annotating the events I tried calling the doLayout from, but basically I went through all of the ones that seemed like it would apply)
    - Other solutions that did not work, stopped annotating after a while :/

    The Solution:
    In the end I stepped back from the problem and tried a different approach. Rather than using a container with an hbox layout type for the row containers I switched the layout type to table.

    This allows me to specify a static heights and widths to the table data elements rather than the images themselves. This means that the images can keep their individual proportional dimensions and fit themselves to their containing table data elements.

    The table data height and width are applied with the config:
    Code:
    layout:{type: 'table', tdAttrs:{style:{width: '255px', height: '200px'}}}
    The change to the controller looks like this:

    Code:
    getPhotos: function (){
            var photoStore = this.getPhotosStore();
            photoStore.proxy.extraParams  = {};
            photoStore.proxy.extraParams.callMethod = "getThumbs";
            var photoContainer  = this.getPhotoContainer();
    
            photoStore.removeAll();
            photoStore.load({
                callback: function (records, operation, success){
                    for (var ct = 0; ct < records.length; ct+=4){
                        // group these into containers of four buttons
                        var row = Ext.create("Ext.container.Container",{
                            layout:{type: 'table', tdAttrs:{style:{width: '255px', height: '200px'}}}
                        })
                        // we have to add the items like this b/c if there is no record (if there's not a number of images evenly divisible by four) we'll get an error 
                        for (var innerLoopCt = 0; innerLoopCt < 4; innerLoopCt++ ){
                            if ( ct + innerLoopCt < records.length){
                                row.add(Ext.create("Ext.Img",{src: records[ct + innerLoopCt].data.thumbPath}));
                            }                        
                        }
                        photoContainer.add(row);    
                    }
                    photoContainer.doLayout();
                }
            });
        },
    Now the images show up as expected:

    Attachment 42530

  3. #2
    Sencha User CSchmitz81's Avatar
    Join Date
    Nov 2012
    Location
    Saint Louis
    Posts
    33
    Vote Rating
    0
    Answers
    3
    CSchmitz81 is on a distinguished road

      0  

    Default Found a work around

    Found a work around


    So for anyone who may run into this problem in the future, here's how I solved my problem.

    The setup:
    I have a directory full of image thumbnails of various dimension that I wanted to return to my application. because the dimensions were not all the same I did not want to specify fixed height and widths for the images.

    The php file I built to return the images from the scanned directory returns the relative path from the root of my web server which is then used by the sencha controller to create image components grouped by four into containers. The structure looks like this:
    - Photo Container
    - Row Container
    - Image Component
    - Image Component
    - Image Component
    - Image Component
    - Row Container
    - Image Component
    - ......
    The problem:
    Because I did not specify a fixed width and height for the image components, the images were returned as tiny blocks that did not take their actual size until the window was resized or the page was reloaded without clearing the cache.
    Screen Shot 2013-03-19 at 9.00.57 PM.png

    Possible solutions that did not work:
    I tried numerous methods to solve the problem and with each of them the resulting image components rendered the same.
    - Calling a doLayout method from the photo container after the row containers have been added to it as children, tried the same with doContainerLayout
    - Calling a doLayout method from the each row container as they are created, tried the same with doContainerLayout
    - Calling a doLayout and doContainerLayout method after the method for getting the images has been called and finishes
    - Adding a listener to the photo container that performs a doLayout, doContainerLayout, or update method call on render, beforerender, activate, etc (I stopped annotating the events I tried calling the doLayout from, but basically I went through all of the ones that seemed like it would apply)
    - Other solutions that did not work, stopped annotating after a while :/

    The Solution:
    In the end I stepped back from the problem and tried a different approach. Rather than using a container with an hbox layout type for the row containers I switched the layout type to table.

    This allows me to specify a static heights and widths to the table data elements rather than the images themselves. This means that the images can keep their individual proportional dimensions and fit themselves to their containing table data elements.

    The table data height and width are applied with the config:
    Code:
    layout:{type: 'table', tdAttrs:{style:{width: '255px', height: '200px'}}}
    The change to the controller looks like this:

    Code:
    getPhotos: function (){
            var photoStore = this.getPhotosStore();
            photoStore.proxy.extraParams  = {};
            photoStore.proxy.extraParams.callMethod = "getThumbs";
            var photoContainer  = this.getPhotoContainer();
    
            photoStore.removeAll();
            photoStore.load({
                callback: function (records, operation, success){
                    for (var ct = 0; ct < records.length; ct+=4){
                        // group these into containers of four buttons
                        var row = Ext.create("Ext.container.Container",{
                            layout:{type: 'table', tdAttrs:{style:{width: '255px', height: '200px'}}}
                        })
                        // we have to add the items like this b/c if there is no record (if there's not a number of images evenly divisible by four) we'll get an error 
                        for (var innerLoopCt = 0; innerLoopCt < 4; innerLoopCt++ ){
                            if ( ct + innerLoopCt < records.length){
                                row.add(Ext.create("Ext.Img",{src: records[ct + innerLoopCt].data.thumbPath}));
                            }                        
                        }
                        photoContainer.add(row);    
                    }
                    photoContainer.doLayout();
                }
            });
        },
    Now the images show up as expected:

    Screen Shot 2013-03-19 at 9.29.43 PM.jpg