[CLOSED] Ext.Net Multicombo subclassing and rendering "tpl" for the items.

  1. #1

    [CLOSED] Ext.Net Multicombo subclassing and rendering "tpl" for the items.

    Hi, I am trying to subclass the MultiCombo control, and since I need to change the item rendering template based on some custom data, I tried to override the "tpl".

    However, I've seen that the currently implemented algorithm is somehow broken when a component has a template already in place:

    function () {
            this.editable = false;
    
            if (!this.tpl) {
                this.tpl = '<tpl for="."><div class="x-combo-list-item {[this.getItemClass()]}">' +
                    '<img src="' + Ext.BLANK_IMAGE_URL + '" class="{[this.getImgClass(values)]}" />' +
                    '<div class="x-mcombo-text">{' + this.displayField + '}</div></div></tpl>';
    
                this.tpl = new Ext.XTemplate(this.tpl, {
                    getItemClass : (function () {
                        if (this.selectionMode === "selection") {
                            return "x-mcombo-nimg-item";
                        }
    
                        return "x-mcombo-img-item";
    
                    }).createDelegate(this),
    Let's say I need all the Multicombo functionality but with a different rendering (for instance putting some rows with different colors, putting a separator... and so on...

    I was going to try overriding the initComponent for the base class, however I would like to check with you if it's the right way to go or not,
    Thanks!
    Last edited by Daniil; Sep 12, 2013 at 2:59 PM. Reason: [CLOSED]
  2. #2
    Hi @adrianot,

    If you want to override a MultiCombo's Tpl, there are two ways.

    1. Override the initComponent function as you are considering. It is OK.

    2. Define a MultiCombo's Tpl property. You can repeat the default Tpl and tweak it with your changes.
  3. #3
    Hi Daniil, yes I did it by overriding InitComponent since I already tried to force the tpl, but as you can see on the MultiCombo JS implementation you see that if "tpl" property replaced server side or before calling InitComponent, I can't make use of the "helper" template functions you added to manage the checkbox state and so on... (getItemClass , ... etc), since they are not added at all.

    In my opinion it would be great to have always those helper functions also when overriding the "tpl" property.

    What do you think?

    Thank you, as always.
    Cheers
  4. #4
    I see your point. Well, agreed, it would be good to have a possibility to override a tpl's HTML markup only keeping the default functions. Though, I think it is possible when a developer needs to override some of those functions keeping the HTML markup. I am talking that there are so many various possibilities which we could support. There should be some limitation of that, I mean on making everything configurable. It would blow the toolkit:)

    Generally speaking, a MultiCombo's template is not supposed to be overridden at all. Albeit, we provided such a possibility if a developer really knows what he does. Currently, I am reluctant to do any change more in that part. Though, it should not be a problem for you. Please demonstrate how I overrode the initComponent.
  5. #5
    Hi Daniil,
    I agree completely with you, currently I managed to override like this :

    Ext.namespace('Portal.Controls');
    
    Portal.Controls.UserOrGroupComboBox = Ext.extend(Ext.net.MultiCombo, {
    
        initComponent: function () {
    
            this.on("beforeselect", function (combo, record, index) {
                if (record.get("ID") === "---") return false;
            });
    
            // build new template.
            var template = ['<tpl for=".">',
                                '<tpl if="ID === \'---\'" >',
                                    '<div class="x-combo-list-item"><hr/></div>',
                                '</tpl>',
                                '<tpl if="ID != \'---\'" >',
                                    '<div class="x-combo-list-item {[this.getItemClass()]}">',
                                        '<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" class="{[this.getImgClass(values)]}" />',
                                        '<div class="x-mcombo-text">{[ values["ObjectDescription"] ]}</div>',
                                    '</div>',
                                '</tpl>',
                            '</tpl>'];
    
            // set initial tpl as plain html
            this.tpl = template.join("");
    
            /* FOLLOWS A SUPERCLASS REPLACEMENT HACK (for tpl) */
            this.editable = false;
            
            this.tpl = new Ext.XTemplate(this.tpl, {
                getItemClass: (function () {
                    if (this.selectionMode === "selection") {
                        return "x-mcombo-nimg-item";
                    }
    
                    return "x-mcombo-img-item";
    
                }).createDelegate(this),
    
                getImgClass: (function (values) {
                    if (this.selectionMode === "selection") {
                        return "";
                    }
    
                    var found = false;
    
                    Ext.each(this.checkedRecords, function (record) {
                        // do not replace == by ===
                        if (values[this.valueField] == record.get(this.valueField)) {
                            found = true;
                            return false;
                        }
                    }, this);
    
                    return found ? "x-grid3-check-col-on" : "x-grid3-check-col";
                }).createDelegate(this, [], true)
            });
    
            this.checkedRecords = [];
    
            Ext.net.MultiCombo.superclass.initComponent.apply(this, arguments);
    
            if (this.selectionPredefined) {
                this.initSelection(this.selectionPredefined);
            }
    
            this.on("beforequery", this.onBeforeQuery);
        }
    });
    
    Ext.reg('userorgroupcombobox', Portal.Controls.UserOrGroupComboBox);
    I am attaching the expected behavior (basically a separator between items, removing the checkbox on the separator, ... and in the next changes a more complex template (2 rows of data... icons and so on...).

    As you can imagine I am not so happy with this implementation (code changes) :-) mainly because if you change the same in the future I would need to replace my code.

    For instance, I think that if you provide a MultiCombo helper method "buildTemplate" that performs the template intiialization logic so that the caller could override it before calling "initComponent" would be great and provide both compatibility with today implemntation, as well as more functionality to the people like me wanting more "control".

    Anyways guys let me say that your framework absolutely ROCKS,
    Again, thank you and have a nice day!
    Adriano
    Attached Thumbnails Click image for larger version. 

Name:	sample.png 
Views:	19 
Size:	18.8 KB 
ID:	6849  
  6. #6
    Thank you for the kind words!

    So, are you willing to see the following change?
    Ext.net.MultiCombo.override({
        setupTpl: function () {
            if (!this.tpl) {
                this.tpl = '<tpl for="."><div class="x-combo-list-item {[this.getItemClass()]}">' +
                    '<img src="' + Ext.BLANK_IMAGE_URL + '" class="{[this.getImgClass(values)]}" />' +
                    '<div class="x-mcombo-text">{' + this.displayField + '}</div></div></tpl>';
    
                this.tpl = new Ext.XTemplate(this.tpl, {
                    getItemClass: (function () {
                        if (this.selectionMode === "selection") {
                            return "x-mcombo-nimg-item";
                        }
    
                        return "x-mcombo-img-item";
    
                    }).createDelegate(this),
    
                    getImgClass: (function (values) {
                        if (this.selectionMode === "selection") {
                            return "";
                        }
    
                        var found = false;
    
                        Ext.each(this.checkedRecords, function (record) {
                            // do not replace == by ===
                            if (values[this.valueField] == record.get(this.valueField)) {
                                found = true;
                                return false;
                            }
                        }, this);
    
                        return found ? "x-grid3-check-col-on" : "x-grid3-check-col";
                    }).createDelegate(this, [], true)
                });
            }
        },
    
        initComponent: function () {
            this.editable = false;
            this.setupTpl();
            this.checkedRecords = [];
    
            Ext.net.MultiCombo.superclass.initComponent.apply(this, arguments);
    
            if (this.selectionPredefined) {
                this.initSelection(this.selectionPredefined);
            }
    
            this.on("beforequery", this.onBeforeQuery);
        }
    });
  7. #7
    Hi Daniil, yes decoupling helps overriding the template without havign to worry about the other initialization stuff, right?

    What is your opinion?
  8. #8
    I think it is a good idea.

    So, did you try my override? Does it suite your needs?

Similar Threads

  1. [CLOSED] "Select All" option in MultiCombo
    By pj_martins in forum 1.x Legacy Premium Help
    Replies: 5
    Last Post: Oct 31, 2013, 9:13 PM
  2. Replies: 6
    Last Post: May 31, 2013, 3:04 AM
  3. [CLOSED] Problems when usin "Content" instead of "Items"
    By Pablo_Azevedo in forum 1.x Legacy Premium Help
    Replies: 2
    Last Post: Jul 24, 2012, 1:43 PM
  4. Replies: 5
    Last Post: May 02, 2012, 5:37 PM
  5. Replies: 0
    Last Post: Mar 24, 2011, 2:20 PM

Posting Permissions