“Ext.getCmp(…) is undefined” in different function

2019-03-06 17:58发布

问题:

I have Extjs code in view, this is it:

createPanelMC: function() {
        this.requiredSign = '<span style="color:red;font-weight:bold" data-qtip="Required">*</span>';
        var panel = Ext.create('Ext.form.Panel', {
            defaultType: 'textfield',
            name: 'nodebPanel',
            width: '100%',
            layout: {
                type: 'auto',
                align: 'stretch'
            },
            items: [{
                xtype   : 'fieldset', 
                name    : 'modlayanan',
                title   : 'Data Pelanggan',
                layout  : 'column',
                width   : '95%',
                margin  : '10',
                items: [{
                    xtype           : 'textfield',
                    name            : 'nomor',
                    id              : 'nomor',
                    fieldLabel      : 'PSTN',
                    emptyText       : 'Nomor...',
                    margin          : '10 0 0 0',
                    width           : 350,
                    labelWidth      : 100,
                    afterLabelTextTpl: this.requiredSign    
                }, {
                    xtype           : 'textfield',
                    fieldLabel      : 'Speedy',
                    name            : 'speedy',
                    id              : 'speedy',
                    margin          : '10 0 10 20',
                    width           : 350,
                    labelWidth      : 100
                },
                this.createTreePaketExist()
                ]
            }],
            dockedItems: [ {
                    xtype: 'toolbar',
                    name: 'tbpaketmc',
                    dock: 'bottom',
                    items: [ {
                            text: '<< Back',
                            action: 'doBack'
                        },'->', {
                            text: 'Submit',
                            action: 'doSubmit'
                        }
                    ]
                }
            ]
        });
        return panel;
    },

i call nomor dan speedy in this.createTreePaketExist() . This is the this.createTreePaketExist() code:

createTreePaketExist: function() {
        var nopstn= Ext.getCmp('nomor').getValue();
        var speedy= Ext.getCmp('speedy').getValue();
        var storeTree = Ext.create('Ext.data.TreeStore', {
            proxy: {
                type: 'ajax',
                method: 'POST',
                url: 'data/newoss_get_paket.php',
                params: { 
                        nopstn:nopstn
                        ,speedy:speedy
                }
            }
        });

    var groupProduct = Ext.create('Ext.tree.Panel', {
        store       : storeTree,
        name        : 'treeProduct',
        rootVisible : false,
        useArrows   : true,
        layout      :'fit',
        margin      : '0 0 0 0',
        autoScroll  : true,
        height      : 150,
        width       : '93%',
        listeners: 
        {
            checkchange: function(node, checked, eOpts){
                 node.eachChild(function(n) {
                node.cascadeBy(function(n){
                    n.set('checked', checked);
                });
            });
            p = node.parentNode;
            var pChildCheckedCount = 0;
            p.suspendEvents();
            p.eachChild(function(c) { 
                if (c.get('checked')) pChildCheckedCount++; 
                    p.set('checked', !!pChildCheckedCount);
                });
            p.resumeEvents();
            }
        }
    });
    return groupProduct; 
},

but it gave an error: Ext.getCmp(...) is undefined. Help me, thanks.

回答1:

The createTreePaketExist will be called during component initialisation, it's unlikely the textfields are actually rendered or even initialised properly at this point, best to use the listeners. You could use refs in your controller to get a reference to these fields automatically or you could listen to the afterrender event and then reference the fields.

I have created a fiddle here that shows how to load the store on form submit, you could also do this on the textfield's change events.

Here is the code for reference:

Ext.application({
    name: 'Fiddle',

    launch: function() {
        var panel = Ext.create('Ext.form.Panel', {
            renderTo: Ext.getBody(),
            defaultType: 'textfield',
            name: 'nodebPanel',
            width: '100%',
            layout: {
                type: 'auto',
                align: 'stretch'
            },
            items: [{
                xtype: 'fieldset',
                name: 'modlayanan',
                title: 'Data Pelanggan',
                layout: 'column',
                width: '95%',
                margin: '10',
                items: [{
                    xtype: 'textfield',
                    name: 'nomor',
                    id: 'nomor',
                    fieldLabel: 'PSTN',
                    emptyText: 'Nomor...',
                    margin: '10 0 0 0',
                    width: 350,
                    labelWidth: 100,
                    afterLabelTextTpl: this.requiredSign
                }, {
                    xtype: 'textfield',
                    fieldLabel: 'Speedy',
                    name: 'speedy',
                    id: 'speedy',
                    margin: '10 0 10 20',
                    width: 350,
                    labelWidth: 100
                }]
            }],
            dockedItems: [{
                xtype: 'toolbar',
                name: 'tbpaketmc',
                dock: 'bottom',
                items: [{
                    text: '<< Back',
                    action: 'doBack'
                }, '->', {
                    text: 'Submit',
                    action: 'doSubmit',
                    bindForm: true,
                    handler: function() {
                        var nopstn = Ext.getCmp('nomor').getValue();
                        var speedy = Ext.getCmp('speedy').getValue();

                        if (nopstn != '' && speedy != '') {
                            var store = Ext.ComponentQuery.query('#treeProduct')[0].getStore();
                            console.log(store);
                            store.load({
                                params: {
                                    nopstn: nopstn,
                                    speedy: speedy
                                }
                            });
                        }
                    }
                }]
            }]
        });

        var storeTree = Ext.create('Ext.data.TreeStore', {
            autoLoad: false,
            proxy: {
                type: 'ajax',
                method: 'POST',
                url: 'data/newoss_get_paket.php'
            }
        });

        var groupProduct = Ext.create('Ext.tree.Panel', {
            renderTo: Ext.getBody(),
            store: storeTree,
            itemId: 'treeProduct',
            name: 'treeProduct',
            rootVisible: false,
            useArrows: true,
            layout: 'fit',
            margin: '0 0 0 0',
            autoScroll: true,
            height: 150,
            width: '93%',
            listeners: {
                checkchange: function(node, checked, eOpts) {
                    node.eachChild(function(n) {
                        node.cascadeBy(function(n) {
                            n.set('checked', checked);
                        });
                    });
                    p = node.parentNode;
                    var pChildCheckedCount = 0;
                    p.suspendEvents();
                    p.eachChild(function(c) {
                        if (c.get('checked')) pChildCheckedCount++;
                        p.set('checked', !! pChildCheckedCount);
                    });
                    p.resumeEvents();
                }
            }
        });
    }
});


回答2:

Ext.getCmp() is not recommended to use in ExtJS code. Instead you should use

Ext.ComponentQuery.query('#nomor')

Where nomor is id of element.

But To resolve your problem try to call this:

Ext.ComponentQuery.query('textfield[name="nomor"]')

or

Ext.getCmp('#nomor')

if this will not help you then the problem in your code structure. May be piece of code that represents getCmp('nomor') is loaded and invoked before piece of code that represents your nomor code. This problem may occur if you do not use MVC