Hybrid View

  1. #1
    Sencha - Community Support Team Condor's Avatar
    Join Date
    Mar 2007
    Location
    The Netherlands
    Posts
    24,246
    Vote Rating
    89
    Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of

      0  

    Default ComponentDataView - Ext components inside a dataview or listview

    ComponentDataView - Ext components inside a dataview or listview


    DataView and ListView are very useful to render store based data as HTML. This extension adds the ability to include Ext components in the HTML without the need to keep track of them (e.g. you won't get a memory leak when you update or delete a record).
    It also supports automatically getting and setting the value from the store if the component is an Ext.form.Field.

    Ext.ux.ComponentDataView:
    Code:
    Ext.ns('Ext.ux');
    Ext.ux.ComponentDataView = Ext.extend(Ext.DataView, {
        defaultType: 'textfield',
        initComponent : function(){
            Ext.ux.ComponentDataView.superclass.initComponent.call(this);
            this.components = [];
        },
        refresh : function(){
            Ext.destroy(this.components);
            this.components = [];
            Ext.ux.ComponentDataView.superclass.refresh.call(this);
            this.renderItems(0, this.store.getCount() - 1);
        },
        onUpdate : function(ds, record){
            var index = ds.indexOf(record);
            if(index > -1){
                this.destroyItems(index);
            }
            Ext.ux.ComponentDataView.superclass.onUpdate.apply(this, arguments);
            if(index > -1){
                this.renderItems(index, index);
            }
        },
        onAdd : function(ds, records, index){
            var count = this.all.getCount();
            Ext.ux.ComponentDataView.superclass.onAdd.apply(this, arguments);
            if(count !== 0){
                this.renderItems(index, index + records.length - 1);
            }
        },
        onRemove : function(ds, record, index){
            this.destroyItems(index);
            Ext.ux.ComponentDataView.superclass.onRemove.apply(this, arguments);
        },
        onDestroy : function(){
            Ext.ux.ComponentDataView.onDestroy.call(this);
            Ext.destroy(this.components);
            this.components = [];
        },
        renderItems : function(startIndex, endIndex){
            var ns = this.all.elements;
            var args = [startIndex, 0];
            for(var i = startIndex; i <= endIndex; i++){
                var r = args[args.length] = [];
                for(var items = this.items, j = 0, len = items.length, c; j < len; j++){
                    c = items[j].render ?
                        c = items[j].cloneConfig() :
                        Ext.create(items[j], this.defaultType);
                    r[j] = c;
                    if(c.renderTarget){
                        c.render(Ext.DomQuery.selectNode(c.renderTarget, ns[i]));
                    }else if(c.applyTarget){
                        c.applyToMarkup(Ext.DomQuery.selectNode(c.applyTarget, ns[i]));
                    }else{
                        c.render(ns[i]);
                    }
                    if(Ext.isFunction(c.setValue) && c.applyValue){
                        c.setValue(this.store.getAt(i).get(c.applyValue));
                        c.on('blur', function(f){
                        	this.store.getAt(this.index).data[this.dataIndex] = f.getValue();
                        }, {store: this.store, index: i, dataIndex: c.applyValue});
                    }
                }
            }
            this.components.splice.apply(this.components, args);
        },
        destroyItems : function(index){
            Ext.destroy(this.components[index]);
            this.components.splice(index, 1);
        }
    });
    Ext.reg('compdataview', Ext.ux.ComponentDataView);
    Ext.ux.ComponentListView:
    Code:
    Ext.ux.ComponentListView = Ext.extend(Ext.ListView, {
        defaultType: 'textfield',
        initComponent : function(){
            Ext.ux.ComponentListView.superclass.initComponent.call(this);
            this.components = [];
        },
        refresh : function(){
            Ext.destroy(this.components);
            this.components = [];
            Ext.ux.ComponentListView.superclass.refresh.apply(this, arguments);
            this.renderItems(0, this.store.getCount() - 1);
        },
        onUpdate : function(ds, record){
            var index = ds.indexOf(record);
            if(index > -1){
                this.destroyItems(index);
            }
            Ext.ux.ComponentListView.superclass.onUpdate.apply(this, arguments);
            if(index > -1){
                this.renderItems(index, index);
            }
        },
        onAdd : function(ds, records, index){
            var count = this.all.getCount();
            Ext.ux.ComponentListView.superclass.onAdd.apply(this, arguments);
            if(count !== 0){
                this.renderItems(index, index + records.length - 1);
            }
        },
        onRemove : function(ds, record, index){
            this.destroyItems(index);
            Ext.ux.ComponentListView.superclass.onRemove.apply(this, arguments);
        },
        onDestroy : function(){
            Ext.ux.ComponentDataView.onDestroy.call(this);
            Ext.destroy(this.components);
            this.components = [];
        },
        renderItems : function(startIndex, endIndex){
            var ns = this.all.elements;
            var args = [startIndex, 0];
            for(var i = startIndex; i <= endIndex; i++){
                var r = args[args.length] = [];
                for(var columns = this.columns, j = 0, len = columns.length, c; j < len; j++){
                    var component = columns[j].component;
                    c = component.render ?
                        c = component.cloneConfig() :
                        Ext.create(component, this.defaultType);
                    r[j] = c;
                    var node = ns[i].getElementsByTagName('dt')[j].firstChild;
                    if(c.renderTarget){
                        c.render(Ext.DomQuery.selectNode(c.renderTarget, node));
                    }else if(c.applyTarget){
                        c.applyToMarkup(Ext.DomQuery.selectNode(c.applyTarget, node));
                    }else{
                        c.render(node);
                    }
                    if(c.applyValue === true){
                    	c.applyValue = columns[j].dataIndex;
                    }
                    if(Ext.isFunction(c.setValue) && c.applyValue){
                        c.setValue(this.store.getAt(i).get(c.applyValue));
                        c.on('blur', function(f){
                        	this.store.getAt(this.index).data[this.dataIndex] = f.getValue();
                        }, {store: this.store, index: i, dataIndex: c.applyValue});
                    }
                }
            }
            this.components.splice.apply(this.components, args);
        },
        destroyItems : function(index){
            Ext.destroy(this.components[index]);
            this.components.splice(index, 1);
        }
    });
    Ext.reg('complistview', Ext.ux.ComponentListView);
    Usage example:
    Code:
    Ext.onReady(function() {
        new Ext.Viewport({
            layout: 'hbox',
            layoutConfig: {
                align: 'stretch'
            },
            defaults: {
                flex: 1
            },
            items: [{
                title: 'ComponentDataView example',
                items: {
                    xtype: 'compdataview',
                    store: [[1, 'One'], [2, 'Two'], [3, 'Three']],
                    itemSelector: 'tbody tr',
                    tpl: '<table><thead><tr><td>Value</td><td>Text</td></tr></thead><tbody><tpl for="."><tr><td></td><td></td></tr></tpl></tbody></table>',
                    items: [{
                        xtype: 'numberfield',
                        minValue: 0,
                        maxValue: 100,
                        renderTarget: 'td:nth(1)',
                        applyValue: 'field1'
                    },{
                        allowBlank: false,
                        renderTarget: 'td:nth(2)',
                        applyValue: 'field2'
                    }]
                }
            },{
                title: 'ComponentListView example',
                items: {
                    xtype: 'complistview',
                    store: [[1, 'One'], [2, 'Two'], [3, 'Three']],
                    columns: [{
                        header: 'Value',
                        width: .5,
                        dataIndex: 'field1',
                        tpl: ' ',
                        component: {
                            xtype: 'numberfield',
                            minValue: 0,
                            maxValue: 100,
                            applyValue: true
                        }
                    },{
                        header: 'Text',
                        width: .5,
                        dataIndex: 'field2',
                        tpl: ' ',
                        component: {
                            allowBlank: false,
                            applyValue: true
                        }
                    }]
                }
            }]
        });
    });

  2. #2
    Ext JS Premium Member
    Join Date
    Jun 2009
    Location
    Eastern WA, US
    Posts
    78
    Vote Rating
    0
    jnicora is on a distinguished road

      0  

    Default


    very slick

  3. #3
    Sencha User
    Join Date
    Mar 2007
    Posts
    64
    Vote Rating
    0
    d0uble_hel1x is on a distinguished road

      0  

    Default


    i was just looking for a solution like this! how do i renderTarget to div or input instead of tr?

    also it would be nice if the form containing your extension can submit and load the folloing json:

    PHP Code:
    {
            
    first:'John',
            
    last:'Doe',
            
    company:'Some Company',
            
    email:'email@abc.com',
            
    phones:[{
                
    phone:'11111111',type:'mobile'
            
    },{
                
    phone:'22222222',type:'office'
            
    },{
                
    phone:'33333333',type:'home'
            
    }]


    this is what i'm experimenting with:

    PHP Code:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <
    html xmlns="http://www.w3.org/1999/xhtml">

    <
    head>

        <
    meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <
    title>Complex form test</title>
        
        <
    link rel='stylesheet' type='text/css' href='http://extjs.com/deploy/dev/resources/css/ext-all.css'/>
        <
    script type="text/javascript"    src="http://extjs.com/deploy/dev/adapter/ext/ext-base.js"></script>
        <script type="text/javascript"    src="http://extjs.com/deploy/dev/ext-all-debug.js"></script>

        
    </head>
    <body>
    </body>
    </html>
        
    <script language="javascript" type="text/javascript">
        Ext.QuickTips.init();
    </script>

    <script type="text/javascript"  language="javascript">

    Ext.ns('Ext.ux.form');

    //MyForm=Ext.extend(Ext.form.FormPanel,{
    MyForm=Ext.extend(Ext.Panel,{

        initComponent:function(){
        
            Ext.apply(this,{
                //baseCls: 'x-plain',
                labelWidth: 55,
                //url:'save-form.php',
                defaultType: 'textfield',
                layout:'hbox',
                items: [{
                    fieldLabel: 'Phone',
                    name: 'phone',
                    anchor:'100%',  // anchor width by percentage
                    xtype:'textfield'
                },{
                    fieldLabel: 'Type',
                    name: 'type',
                    anchor: '100%'  // anchor width by percentage
                }]

            })
            
            MyForm.superclass.initComponent.call(this)
        },

        initFields : function(){
            //var f = this.form;
            var formPanel = this;
            var fn = function(c){
                if(formPanel.isField(c)){
                    //f.add(c);
                }if(c.isFieldWrap){
                    Ext.applyIf(c, {
                        labelAlign: c.ownerCt.labelAlign,
                        labelWidth: c.ownerCt.labelWidth,
                        itemCls: c.ownerCt.itemCls
                    });
                    //f.add(c.field);
                }else if(c.doLayout && c != formPanel){
                    Ext.applyIf(c, {
                        labelAlign: c.ownerCt.labelAlign,
                        labelWidth: c.ownerCt.labelWidth,
                        itemCls: c.ownerCt.itemCls
                    });
                    if(c.items){
                        c.items.each(fn, this);
                    }
                }
            };
            this.items.each(fn, this);
        },

        onRender : function(ct, position){
            this.initFields();
            Ext.FormPanel.superclass.onRender.call(this, ct, position);
            //this.form.initEl(this.body);
        },
        isField : function(c) {
            return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
        },

        setValues : function(values){
            if(Ext.isArray(values)){ // array of objects
                for(var i = 0, len = values.length; i < len; i++){
                    var v = values[i];
                    var f = this.findField(v.id);
                    if(f){
                        f.setValue(v.value);
                        if(this.trackResetOnLoad){
                            f.originalValue = f.getValue();
                        }
                    }
                }
            }else{ // object hash
                var field, id;
                for(id in values){
                    if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
                        field.setValue(values[id]);
                        if(this.trackResetOnLoad){
                            field.originalValue = field.getValue();
                        }
                    }
                }
            }
            return this;
        },

        findField : function(id){
            var field = this.items.get(id);
            if(!Ext.isObject(field)){
                this.items.each(function(f){
                    if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
                        field = f;
                        return false;
                    }
                });
            }
            return field || null;
        }    
        
        
    })

    Ext.ux.form.ArrayField = Ext.extend(Ext.form.Field,{
        
        onRender : function(ct, position){

            this.panel =new Ext.Panel({
                renderTo: ct,
                width:230,
                height:50,
                autoScroll:true,
                layout:'vbox',
                items:[]
                //layout:'vbox',
            });
            this.el=this.panel.getEl();
        
            //Ext.ux.form.ArrayField.superclass.onRender.call(this, ct, position);
            
            this.hiddenField =  Ext.DomHelper.append(this.el,{tag:'input', type:'hidden',name:this.name});
        },
        
        setValue:function(val) {

            var v =  Ext.util.JSON.encode(val);
            this.hiddenField.value=v;
            //alert(v);        
            //this.panel.removeAll();

            for (var i=0;i<val.length;i++){
                var f = new MyForm()
                this.panel.add(f)
                this.panel.doLayout();   
                f.setValues(val[i])
            }
            
        },
        
        getValues:function(){
        }
    });

    // register xtype
    Ext.reg('arrayfield', Ext.ux.form.ArrayField);

    </script>

    <script type="text/javascript">

    Ext.onReady(function(){

        var f = new Ext.FormPanel({
            labelWidth: 75,
            url:'save-form.php',
            frame:true,
            title: 'Simple Form',
            bodyStyle:'padding:5px 5px 0',
            width: 350,
            defaults: {width: 230},
            defaultType: 'textfield',

            items: [{
                    fieldLabel: 'First Name',
                    name: 'first',
                    allowBlank:false
                },{
                    fieldLabel: 'Last Name',
                    name: 'last'
                },{
                    fieldLabel: 'Company',
                    name: 'company'
                }, {
                    fieldLabel: 'Email',
                    name: 'email',
                    vtype:'email'
                }, new Ext.form.TimeField({
                    fieldLabel: 'Time',
                    name: 'time',
                    minValue: '8:00am',
                    maxValue: '6:00pm'
                }),
                this.a=new Ext.ux.form.ArrayField({name:'items',form:MyForm})
            ],

            buttons: [{
                text: 'Save',
                handler: function(){
                    var i=0;
                }, 
                scope:this
            },{
                text: 'Cancel'
            }]
        });

        f.render(document.body);
        
        var rec={}
        rec.data={
            first:'John',
            last:'Doe',
            company:'Some Company',
            email:'email@abc.com',
            items:[{
                phone:'11111111',type:'mobile'
            },{
                phone:'22222222',type:'office'
            },{
                phone:'33333333',type:'home'
            }]
        }
        
        f.form.loadRecord(rec);
        
    })


    </script> 

  4. #4
    Sencha - Services Team Stju's Avatar
    Join Date
    Dec 2008
    Location
    Redwood city, California
    Posts
    288
    Vote Rating
    3
    Stju is on a distinguished road

      0  

    Default


    Someone before asked how to render component in different place, other than TD.. As the question remained unanswered, just posting some examples.
    To render component in different place of template use CSS structural pseudo classes!
    For example, to have component in 8th div in template :
    Code:
    renderTarget: 'div:nth(8)'
    second li
    Code:
    renderTarget: 'li:nth(2)'
    third child of foo
    Code:
    renderTarget: 'foo:nth-child(3)'

  5. #5
    Sencha - Community Support Team Condor's Avatar
    Join Date
    Mar 2007
    Location
    The Netherlands
    Posts
    24,246
    Vote Rating
    89
    Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of

      0  

    Default


    I'm not a big fan of using 'nth', because changing your HTML markup would directly invalidate your render targets.

    I would assign a class="my-target" to the target element and use a '.my-target' selector.

  6. #6
    Ext User
    Join Date
    May 2007
    Location
    Brasília, DF, Brasil
    Posts
    17
    Vote Rating
    0
    daniel.rochetti is on a distinguished road

      0  

    Default


    Hey guys,

    I think rendering the component in diferent targets is not the real problem here. Try to think about the use case I said before: a DataView which display products as its items and each item will have its HTML markup as usual and two components: a button and a rating comp.

    As a possible solution I think extending the XTemplate to provide component building capabilities, something like:

    Code:
    <tpl for".">
        <div id="product_{id}">
            <img />
            <div>
                <comp name="rating" />
            </div>
            <p>{name}</p>
            <p>{shortDescription}</p>
            <div>
                <comp name="button" />
            </div>
        </div>
    </tpl>
    Then, when the template proccessor finds a <comp> tag it call a function, which is reponsible for building that component:
    Code:
    function(compName, values) {
        // create the component and return so the template can render it
    }
    It should also provide some cache capability to avoid creating the same component for the same item more than one time. Probably it should handle unique IDs too, just like Ext does.
    I'm not sure if I was clear in my example, but ASAP I'll work on some code.
    Last edited by daniel.rochetti; 20 Apr 2010 at 12:20 AM. Reason: typos

  7. #7
    Sencha User
    Join Date
    Mar 2007
    Posts
    64
    Vote Rating
    0
    d0uble_hel1x is on a distinguished road

      0  

    Default


    i replied earlier but somehow it had to be approved by the moderator. any idea why is it so?

  8. #8
    Ext JS Premium Member
    Join Date
    Feb 2009
    Posts
    2
    Vote Rating
    0
    gerrye is on a distinguished road

      0  

    Default onDestroy error

    onDestroy error


    I had to patch onDestroy with these:

    Code:
    Ext.override(Ext.ux.ComponentListView, {
        onDestroy : function(){
            Ext.ux.ComponentListView.superclass.onDestroy.call(this);
            Ext.destroy(this.components);
            this.components = [];
        },
    });
    
    Ext.override(Ext.ux.ComponentDataView, {
        onDestroy : function(){
            Ext.ux.ComponentDataView.superclass.onDestroy.call(this);
            Ext.destroy(this.components);
            this.components = [];
        },
    });

  9. #9
    Ext User
    Join Date
    Sep 2009
    Posts
    18
    Vote Rating
    0
    t800t8 is on a distinguished road

      0  

    Default


    Sorry, it's my fault. Work properly :-)

  10. #10
    Sencha - Community Support Team Condor's Avatar
    Join Date
    Mar 2007
    Location
    The Netherlands
    Posts
    24,246
    Vote Rating
    89
    Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of Condor has much to be proud of

      0  

    Default


    Quote Originally Posted by t800t8 View Post
    Seems it doesn't work with ComboBox. All options are available but the input field is empty even that field has value.
    Are you sure the combobox store is loaded when the dataview is rendered?

    (also see this feature request)

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi