1
votes

I have a list of images that I can choose from, and each one of them has different dimensions. In order to maintain aspect ratio, I'm only setting the width on the image, so the browser determines which height the image should be given. Unfortunately, because I don't have a height, Ext JS is unsure what height to give the container, so it doesn't update it after the first image is rendered.

In the example below, you'll see the first image renders properly and sets the height of the panel's body. If you select the other image in the combobox, it won't set the height, and it'll be cut off. However, if you uncomment the bodyCls property, and re-run the example, it will behave as it should... the image selection changes the height of the panel dynamically.

This seems a little hacky to me, and I don't like using float: left directly, but I want these items to be laid out in an hbox fashion, so I'm wondering if there's a better way of accomplishing this. Does someone have a better solution?

And no, I don't want to use object-fit or background-size: cover;

Here's the Fiddle and code:

Ext.application({
    name: 'Fiddle',

    launch: function () {
        var f = Ext.create('Ext.form.Panel', {
            renderTo: Ext.getBody(),
            border: true,
            bodyStyle: 'border-color: blue !important;',
            height: 'auto',
            referenceHolder: true,
            // layout: {
            //     type: 'hbox',
            //     columns: 2
            // },
            // layout: 'fit',
            defaults: {
                style: 'float: left;'
            },
            // This style add height: 100% to the body
            // bodyCls: 'blah',
            margin: 5,
            bodyPadding: 5,
            viewModel: {
                stores: {
                    logosStore: {
                        autoLoad: true,
                        proxy: {
                            url: 'data1.json',
                            type: 'ajax'
                        }
                    }
                }
            },
            items: [{
                xtype: 'image',
                width: 200,
                reference: 'blah',
                hidden: true,
                bind: {
                    src: '{record.logoSrc}',
                    hidden: '{!record.logoSrc}'
                }
            }, {
                xtype: 'combobox',
                valueField: 'logoFileId',
                displayField: 'name',
                queryMode: 'local',
                forceSelection: true,
                margin: '0 0 0 40',
                value: 2,
                listConfig: {
                    itemTpl: '<img src="{logoSrc}" style="max-height: 40px;" />'
                },
                bind: {
                    store: '{logosStore}',
                    selection: '{record}'
                },
                listeners: {
                    select: function (combo, record) {
                        f.getViewModel().notify();
                        // f.setHeight(f.lookupReference('blah').getHeight());
                        // f.lookupReference('blah').getEl().dom.setAttribute('background-image', 'url("' + record.get('logoSrc') + '")');
                    }
                }
            }]
        })
    }
});

EDIT My solution starts to break down when you have my component being used in another container with several other components. See this Fiddle, but it works if you uncomment the cls property in the MyForm component... just seems wrong that I have to add height: 100% !important to everything. Like maybe there's a layout that I could use instead.

1
Does in css: "margin 0 auto" works ?Tejas
Where is the "example below"?scebotari66
I'm sorry y'all... I totally spaced on not having the example. It's there now.incutonez

1 Answers

1
votes

I did come up with a solution, and that was to employ a little bit of JavaScript... I basically wait for the image to load, grab the current height of the image, and update the maxHeight of its container, so it can report its height back to its parent container. The one odd thing is, if the maxHeight is below a certain threshold, I want to keep it at 150, and if the threshold is hit twice or more, when I do setMaxHeight(150), it doesn't actually update the height of the image. That's why I setMaxHeight(null) first if the threshold hasn't been met. An example of this was when I selected the 2nd image first, and then the 3rd image... the 3rd image would be cut off if I didn't setMaxHeight(null).

I think this is an acceptable solution, but once again, I'm wondering if there's a layout that'll do this for me, or I'm not understanding a certain layout or nesting components.

Fiddle and code:

Ext.application({
    name: 'Fiddle',

    launch: function () {
        Ext.define('MyForm', {
            extend: 'Ext.form.Panel',
            alias: 'widget.myForm',
            border: true,
            bodyStyle: 'border-color: blue !important;',
            referenceHolder: true,
            scrollable: true,
            layout: 'fit',
            margin: 5,
            bodyPadding: 5,
            tools: [{
                xtype: 'button'
            }],
            viewModel: {
                stores: {
                    logosStore: {
                        autoLoad: true,
                        proxy: {
                            url: 'data1.json',
                            type: 'ajax'
                        }
                    }
                }
            },
            items: [{
                xtype: 'container',
                reference: 'blah2',
                scrollable: true,
                height: 150,
                maxHeight: 150,
                layout: {
                    type: 'hbox'
                },
                items: [{
                    xtype: 'image',
                    width: 200,
                    reference: 'blah',
                    hidden: true,
                    bind: {
                        src: '{record.logoSrc}',
                        hidden: '{!record.logoSrc}'
                    },
                    listeners: {
                        el: {
                            load: function () {
                                f.getViewModel().notify();
                                var blah2 = f.lookupReference('blah2');
                                var height = f.lookupReference('blah').getHeight();
                                if (height < 150) {
                                    height = 150;
                                    blah2.setMaxHeight(null);
                                }
                                console.log(blah2.setMaxHeight(height), height);
                            }
                        }
                    }
                }, {
                    xtype: 'combobox',
                    valueField: 'logoFileId',
                    displayField: 'name',
                    queryMode: 'local',
                    forceSelection: true,
                    margin: '0 0 0 40',
                    value: 2,
                    width: 350,
                    listConfig: {
                        itemTpl: '<img src="{logoSrc}" style="max-height: 40px;" />'
                    },
                    bind: {
                        store: '{logosStore}',
                        selection: '{record}'
                    }
                }]
            }]
        });
        var f = Ext.create('MyForm', {
            renderTo: Ext.getBody()
        });
    }
});