6

I am using ExtJS 4.1. I have a TreePanel which I bind to one of two TreeStore. After I rebind a store & expand collapse nodes, records are getting duplicate & I see error Uncaught TypeError: Cannot read property 'internalId' of undefined

Another issue is, I am only able to bind store once. When i call treePanel.setRootNode() second time it does not work (irrespective of whether I expand the nodes or not).

Look at this fiddle

Here is the code:

var sportsStore = Ext.create('Ext.data.TreeStore', {
  root: {
    expanded: true,
    id: 133,
    children: [{
        text: "Audi",
        id: 1,
        leaf: true
      },
      {
        text: "sports cars",
        expanded: true,
        id: 2,
        children: [{
            id: 3,
            text: "Porsche",
            leaf: true
          },
          {
            text: "Mustang",
            id: 4,
            leaf: true
          }
        ]
      },
      {
        text: "Jaguar",
        id: 5,
        leaf: true
      }
    ]
  }
});


var carStore = Ext.create('Ext.data.TreeStore', {
  root: {
    expanded: true,
    id: 1444,
    children: [{
        id: 6,
        text: "Toyota",
        leaf: true
      },
      {
        text: "cars",
        id: 7,
        expanded: true,
        children: [{
            id: 8,
            text: "honda",
            leaf: true
          },
          {
            text: "Nissan",
            id: 9,
            leaf: true
          }
        ]
      },
      {
        text: "Kia",
        id: 10,
        leaf: true
      }
    ]
  }
});



Ext.create('Ext.panel.Panel', {
  title: 'Car Simple Tree',
  width: 300,
  height: 450,

  renderTo: Ext.getBody(),

  items: [{
      xtype: 'button',
      text: 'sports',
      handler: function() {
        alert('You clicked the sports button!');
        var t = Ext.getCmp('tp');

        t.setRootNode(sportsStore.getRootNode());
      }
    },

    {
      xtype: 'button',
      text: 'car',
      handler: function() {
        alert('You clicked the car button!');
        var t = Ext.getCmp('tp');

        t.setRootNode(carStore.getRootNode());
      }
    },
    {

      xtype: 'treepanel',
      id: 'tp',
      store: sportsStore,
      rootVisible: false,
      lines: true
    }
  ]


});
SharpCoder
  • 18,279
  • 43
  • 153
  • 249
  • 2
    Check that **[FIDDLE](https://fiddle.sencha.com/fiddle/2jl9)** this will help you. – Narendra Jadhav Jul 25 '18 at 06:22
  • @NarendraJadhav: You are not using store in this case. when we use store, we run into this issue. – SharpCoder Aug 08 '18 at 15:58
  • @SharpCoder ware you able to see if the answer I had bellow helps? – Akrion Aug 13 '18 at 20:51
  • @Akrion: it is working. But its a hacky way to achieve the desired result. Let's see if we get more answers in next two days (which I doubt). – SharpCoder Aug 13 '18 at 21:31
  • @SharpCoder hey no rush. Just was wondering if you have a chance to see it and your opinion on the result. As I said `it might not be your cup of tea` :). Earlier version of Sencha as far as I remember had plenty of stuff like these where hacks ware pretty much required. I would love to see an actual solution without re-create as well. – Akrion Aug 13 '18 at 21:34

2 Answers2

1

Just for the record you know your problem is solved in one line in 6.0 with just calling setStore() and passing as parameter the store you want right?

Here is a demo of this working in 6.0.

I played with this for a good amount of time and although my Sencha is somewhat rusty (used to be a big fan back in the day) I managed to get something working.

Now it might not be your cup of tea but it does exactly what you want ... you change the stores and expanding/collapsing works etc. The trick is I dynamically re-create the tree on every store change and set the store as the default store to that new tree. The decommissioned trees are removed by Ext.destroy etc.

Here is that Ext 4.1 working example in Fiddle

And here is the code for your reference:

Ext.define('Thing', {
  extend: 'Ext.data.Model',
  fields: [{
    name: 'id',
    type: 'int'
  }, {
    name: 'text',
    type: 'string'
  }]
});

var sportsStore = Ext.create('Ext.data.TreeStore', {
  model: 'Thing',
  storeId: 'sportsStore',
  clearOnLoad: true,
  root: {
    expanded: true,
    id: 133,
    children: [{
      text: "Audi",
      id: 1,
      leaf: true
    }, {
      text: "sports cars",
      expanded: true,
      id: 2,
      children: [{
        id: 3,
        text: "Porsche",
        leaf: true
      }, {
        text: "Mustang",
        id: 4,
        leaf: true
      }]
    }, {
      text: "Jaguar",
      id: 5,
      leaf: true
    }]
  }
});
var carStore = Ext.create('Ext.data.TreeStore', {
  model: 'Thing',
  storeId: 'carStore',
  clearOnLoad: true,
  root: {
    expanded: true,
    id: 1444,
    children: [{
      id: 6,
      text: "Toyota",
      leaf: true
    }, {
      text: "cars",
      id: 7,
      expanded: true,
      children: [{
        id: 8,
        text: "honda",
        leaf: true
      }, {
        text: "Nissan",
        id: 9,
        leaf: true
      }]
    }, {
      text: "Kia",
      id: 10,
      leaf: true
    }]
  }
});
// This function does the magic by removing/then destroying the old tree and 
// adding the newly created one with default new store setup
function setupTree(storeName) {
  var pnl = Ext.getCmp('pnl');
  var treePanel = Ext.getCmp('tp')
  if (treePanel) {
    pnl.remove(treePanel)
    Ext.destroy(treePanel)
  }
  pnl.add(new Ext.create('Ext.tree.Panel', {
    id: 'tp',
    autoRender: true,
    rootVisible: false,
    store: storeName,
    animate: false,
    lines: true
  }))
}

Ext.create('Ext.panel.Panel', {
  id: 'pnl',
  title: 'Car Simple Tree',
  width: 300,
  height: 450,
  renderTo: Ext.getBody('#canvas'),
  items: [{
    xtype: 'button',
    text: 'sports',
    handler: function() {
      setupTree('sportsStore')
    }
  }, {
    xtype: 'button',
    text: 'car',
    handler: function() {
      setupTree('carStore')
    }
  }],
  listeners: {
    afterrender: function(self) {
      setupTree('sportsStore')
    }
  }
});

I also added ids to the stored as well as defined a model for the stores just to be more close to best practices etc.

The thing that makes this move is the setupTree function which looks for a tree with certain id, if it finds it cleans it and then creates a new one with a default store the one we clicked on.

Hope this helps.

Akrion
  • 18,117
  • 1
  • 34
  • 54
0

I suggest the following approach, which may be a workaround, but ExtJS 4.1 version has some issues in UpdateIndexes() method:

  • define an empty tree store (baseStore) and bind it to the tree panel
  • on every button click, fill this empty store with data from appropriate store.

Code:

Ext.onReady(function(){

        Ext.QuickTips.init();
        Ext.FocusManager.enable();

        // Stores
        var baseStore = Ext.create('Ext.data.TreeStore', {
            root: {
                expanded: true,
                leaf: false,
                children: []
            }
        });
        var sportsStore = Ext.create('Ext.data.TreeStore', {
            root: {
            expanded: true,
            id: 133,
            children: [
            {
                text: "Audi",
                id: 1,
                leaf: true
                },
                {
                text: "sports cars",
                expanded: true,
                id: 2,
                children: [{
                    id: 3,
                    text: "Porsche",
                    leaf: true
                    },
                    {
                    text: "Mustang",
                    id: 4,
                    leaf: true
                    }
                ]
                },
                {
                text: "Jaguar",
                id: 5,
                leaf: true
                }
            ]
            }
        });
        var carStore = Ext.create('Ext.data.TreeStore', {
            root: {
            expanded: true,
            id: 1444,
            children: [
                {
                id: 6,
                text: "Toyota",
                leaf: true
                },
                {
                text: "cars",
                id: 7,
                expanded: true,
                children: [
                    {
                    id: 8,
                    text: "honda",
                    leaf: true
                    },
                    {
                    text: "Nissan",
                    id: 9,
                    leaf: true
                    }
                ]
                },
                {
                text: "Kia",
                id: 10,
                leaf: true
                }
            ]
            }
        });                 

        // Filling data
        function fillStore(xparent, xnode) {
            for (var i = 0; i < xnode.childNodes.length; i++) {
                var current = xnode.childNodes[i];
                var added = xparent.appendChild(
                    {
                    text: current.data.text,
                    leaf: current.data.leaf,
                    id: current.data.id
                    }
                );
                if (current.data.leaf === false) {
                    fillStore(added, current);
                }
            }
        }
        function setStore(store) {
            var root = baseStore.getRootNode();

            if (root.hasChildNodes()) {
                root.removeAll();
            }
            fillStore(root, store.getRootNode());
        }

        // First fill
        setStore(carStore);

    Ext.create('Ext.panel.Panel', {
        title: 'Car Simple Tree',
        width: 300,
        height: 450,

        renderTo: Ext.getBody(),

        items: [
            {
            xtype: 'button',
            text: 'sports',
            handler: function() {
                alert('You clicked the sports button!');
                var t = Ext.getCmp('tp');

                setStore(sportsStore);
            }
            },
            {
            xtype: 'button',
            text: 'car',
            handler: function() {
                alert('You clicked the car button!');
                var t = Ext.getCmp('tp');

                setStore(carStore);
                }
            },
            {
            xtype: 'treepanel',
            id: 'tp',
            store: baseStore,
            rootVisible: false,
            lines: true
            }
        ]
    });
});

Notes:

Working fiddle can be found here.

Zhorov
  • 28,486
  • 6
  • 27
  • 52
  • This is great. Only issue is, the model that I bind to my store has 15+ properties. and in some cases I have close to 300 nodes. In my case `fillStore()` will get long. I also need to evaluate the performance. – SharpCoder Aug 14 '18 at 14:27