Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: Child node unable to expand (Needs Info)

    Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Sencha Premium Member
    Join Date
    Oct 2013
    Posts
    18

    Default Child node unable to expand (Needs Info)

    Steps to reproduce:
    1. Create a three-level tree
    2. Expand first level node with mouse click
    3. Programmatically expand the first level node (that is already expanded)
    4. Try to expand any of the child node (second level) of the expanded node, they are unable to expand.

  2. #2
    Sencha Sr Product Manager
    Join Date
    Jan 2012
    Location
    Arlington, WA
    Posts
    1,178

    Default

    Which version of GXT?

  3. #3
    Sencha Premium Member
    Join Date
    Oct 2013
    Posts
    18

    Default

    3.0.6

  4. #4
    Sencha Sr Product Manager
    Join Date
    Jan 2012
    Location
    Arlington, WA
    Posts
    1,178

    Default

    I'm digging into this more, back with more shortly.

    Brandon

  5. #5
    Sencha Sr Product Manager
    Join Date
    Jan 2012
    Location
    Arlington, WA
    Posts
    1,178

    Default

    I'm not able to reproduce this issue yet. I've made a test case to replicate it.

    I'm wondering if an exception is getting thrown, possibly an assertion. Do you have assertion exceptions on when debugging?

    Test case. Could try this test case out and/or modify it so it replicates the issue and pass it back?
    Code:
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    
    
    import com.google.gwt.user.client.ui.RootPanel;
    import com.google.gwt.user.client.ui.Widget;
    import com.sencha.gxt.core.client.ValueProvider;
    import com.sencha.gxt.data.shared.ModelKeyProvider;
    import com.sencha.gxt.data.shared.TreeStore;
    import com.sencha.gxt.widget.core.client.button.ButtonBar;
    import com.sencha.gxt.widget.core.client.button.TextButton;
    import com.sencha.gxt.widget.core.client.container.FlowLayoutContainer;
    import com.sencha.gxt.widget.core.client.container.MarginData;
    import com.sencha.gxt.widget.core.client.container.Viewport;
    import com.sencha.gxt.widget.core.client.event.SelectEvent;
    import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler;
    import com.sencha.gxt.widget.core.client.tree.Tree;
    
    
    public class TreeExpandTest {
    
    
      private FolderDto beethoven;
    
    
      public TreeExpandTest() {
        Viewport viewport = new Viewport();
        viewport.add(asWidget());
    
    
        RootPanel.get().add(viewport);
      }
    
    
      class KeyProvider implements ModelKeyProvider<BaseDto> {
        @Override
        public String getKey(BaseDto item) {
          return (item instanceof FolderDto ? "f-" : "m-") + item.getId().toString();
        }
      }
    
    
      public Widget asWidget() {
        TreeStore<BaseDto> store = new TreeStore<BaseDto>(new KeyProvider());
    
    
        FolderDto root = getMusicRootFolder();
        for (BaseDto base : root.getChildren()) {
          store.add(base);
          if (base instanceof FolderDto) {
            processFolder(store, (FolderDto) base);
          }
        }
    
    
        final Tree<BaseDto, String> tree = new Tree<BaseDto, String>(store, new ValueProvider<BaseDto, String>() {
    
    
          @Override
          public String getValue(BaseDto object) {
            return object.getName();
          }
    
    
          @Override
          public void setValue(BaseDto object, String value) {
          }
    
    
          @Override
          public String getPath() {
            return "name";
          }
        });
        tree.setWidth(300);
    
    
        ButtonBar buttonBar = new ButtonBar();
        buttonBar.add(new TextButton("Expand All", new SelectHandler() {
          @Override
          public void onSelect(SelectEvent event) {
            tree.expandAll();
          }
        }));
        buttonBar.add(new TextButton("Collapse All", new SelectHandler() {
          @Override
          public void onSelect(SelectEvent event) {
            tree.collapseAll();
          }
        }));
        buttonBar.add(new TextButton("Expand Node 1", new SelectHandler() {
          @Override
          public void onSelect(SelectEvent event) {
            tree.setExpanded(beethoven, true);
          }
        }));
        buttonBar.setLayoutData(new MarginData(4));
        
        FlowLayoutContainer con = new FlowLayoutContainer();
        con.add(buttonBar);
        con.add(tree);
        return con;
      }
    
    
      public void onModuleLoad() {
        RootPanel.get().add(asWidget());
      }
    
    
      private void processFolder(TreeStore<BaseDto> store, FolderDto folder) {
        for (BaseDto child : folder.getChildren()) {
          store.add(folder, child);
          if (child instanceof FolderDto) {
            processFolder(store, (FolderDto) child);
          }
        }
      }
    
    
      public FolderDto getMusicRootFolder() {
        FolderDto root = makeFolder("Root");
    
    
        FolderDto author = makeFolder("Beethoven");
        beethoven = author;
        List<BaseDto> children = new ArrayList<BaseDto>();
        children.add(author);
        root.setChildren(children);
    
    
        FolderDto genre = makeFolder("Quartets");
        author.addChild(genre);
    
    
        FolderDto quartets = genre;
    
    
        genre.addChild(makeMusic("Six String Quartets", author, genre));
        genre.addChild(makeMusic("Three String Quartets", author, genre));
        genre.addChild(makeMusic("Grosse Fugue for String Quartets", author, genre));
    
    
        genre = makeFolder("Sonatas");
        quartets.addChild(genre);
    
    
        genre.addChild(makeMusic("Sonata in A Minor", author, genre));
        genre.addChild(makeMusic("Sonata in F Major", author, genre));
    
    
        genre = makeFolder("Concertos");
        author.addChild(genre);
    
    
        genre.addChild(makeMusic("No. 1 - C", author, genre));
        genre.addChild(makeMusic("No. 2 - B-Flat Major", author, genre));
        genre.addChild(makeMusic("No. 3 - C Minor", author, genre));
        genre.addChild(makeMusic("No. 4 - G Major", author, genre));
        genre.addChild(makeMusic("No. 5 - E-Flat Major", author, genre));
    
    
        genre = makeFolder("Symphonies");
        author.addChild(genre);
    
    
        genre.addChild(makeMusic("No. 1 - C Major", author, genre));
        genre.addChild(makeMusic("No. 2 - D Major", author, genre));
        genre.addChild(makeMusic("No. 3 - E-Flat Major", author, genre));
        genre.addChild(makeMusic("No. 4 - B-Flat Major", author, genre));
        genre.addChild(makeMusic("No. 5 - C Minor", author, genre));
        genre.addChild(makeMusic("No. 6 - F Major", author, genre));
        genre.addChild(makeMusic("No. 7 - A Major", author, genre));
        genre.addChild(makeMusic("No. 8 - F Major", author, genre));
        genre.addChild(makeMusic("No. 9 - D Minor", author, genre));
    
    
        author = makeFolder("Brahms");
        root.addChild(author);
    
    
        genre = makeFolder("Concertos");
        author.addChild(genre);
    
    
        genre.addChild(makeMusic("Violin Concerto", author, genre));
        genre.addChild(makeMusic("Double Concerto - A Minor", author, genre));
        genre.addChild(makeMusic("Piano Concerto No. 1 - D Minor", author, genre));
        genre.addChild(makeMusic("Piano Concerto No. 2 - B-Flat Major", author, genre));
    
    
        genre = makeFolder("Quartets");
        author.addChild(genre);
    
    
        genre.addChild(makeMusic("Piano Quartet No. 1 - G Minor", author, genre));
        genre.addChild(makeMusic("Piano Quartet No. 2 - A Major", author, genre));
        genre.addChild(makeMusic("Piano Quartet No. 3 - C Minor", author, genre));
        genre.addChild(makeMusic("String Quartet No. 3 - B-Flat Minor", author, genre));
    
    
        genre = makeFolder("Sonatas");
        author.addChild(genre);
    
    
        genre.addChild(makeMusic("Two Sonatas for Clarinet - F Minor", author, genre));
        genre.addChild(makeMusic("Two Sonatas for Clarinet - E-Flat Major", author, genre));
    
    
        genre = makeFolder("Symphonies");
        author.addChild(genre);
    
    
        genre.addChild(makeMusic("No. 1 - C Minor", author, genre));
        genre.addChild(makeMusic("No. 2 - D Minor", author, genre));
        genre.addChild(makeMusic("No. 3 - F Major", author, genre));
        genre.addChild(makeMusic("No. 4 - E Minor", author, genre));
    
    
        author = makeFolder("Mozart");
        root.addChild(author);
    
    
        genre = makeFolder("Concertos");
        author.addChild(genre);
    
    
        genre.addChild(makeMusic("Piano Concerto No. 12", author, genre));
        genre.addChild(makeMusic("Piano Concerto No. 17", author, genre));
        genre.addChild(makeMusic("Clarinet Concerto", author, genre));
        genre.addChild(makeMusic("Violin Concerto No. 5", author, genre));
        genre.addChild(makeMusic("Violin Concerto No. 4", author, genre));
    
    
        return root;
      }
    
    
      private static long autoId = 0;
    
    
      private FolderDto makeFolder(String name) {
        FolderDto theReturn = new FolderDto(++autoId, name);
        theReturn.setChildren((List<BaseDto>) new ArrayList<BaseDto>());
        return theReturn;
      }
    
    
      private MusicDto makeMusic(String name, FolderDto author, FolderDto genre) {
        return makeMusic(name, author.getName(), genre.getName());
      }
    
    
      private MusicDto makeMusic(String name, String author, String genre) {
        return new MusicDto(++autoId, name, genre, author);
      }
    
    
      public class BaseDto implements Serializable {
    
    
        private Long id;
        private String name;
    
    
        protected BaseDto() {
    
    
        }
    
    
        public BaseDto(Long id, String name) {
          this.id = id;
          this.name = name;
        }
    
    
        public Long getId() {
          return id;
        }
    
    
        public void setId(Long id) {
          this.id = id;
        }
    
    
        public String getName() {
          return name;
        }
    
    
        public void setName(String name) {
          this.name = name;
        }
    
    
      }
    
    
      public class FolderDto extends BaseDto {
    
    
        private List<BaseDto> children;
    
    
        protected FolderDto() {
    
    
        }
    
    
        public FolderDto(Long id, String name) {
          super(id, name);
        }
    
    
        public List<BaseDto> getChildren() {
          return children;
        }
    
    
        public void setChildren(List<BaseDto> children) {
          this.children = children;
        }
    
    
        public void addChild(BaseDto child) {
          getChildren().add(child);
        }
      }
    
    
      public class MusicDto extends BaseDto {
    
    
        private String genre;
        private String author;
    
    
        protected MusicDto() {
        }
    
    
        public MusicDto(Long id, String name, String genre, String author) {
          super(id, name);
          this.genre = genre;
          this.author = author;
        }
    
    
        public String getGenre() {
          return genre;
        }
    
    
        public void setGenre(String genre) {
          this.genre = genre;
        }
    
    
        public String getAuthor() {
          return author;
        }
    
    
        public void setAuthor(String author) {
          this.author = author;
        }
    
    
      }
    }
    Thanks,
    Brandon

  6. #6
    Sencha Premium Member
    Join Date
    Oct 2013
    Posts
    18

    Default

    Apologies I missed out the reply. I tried it with your test case and it works. I realised the issue only happen when all the nodes in the the subtree of the selected/expanded node are "highlighted" with the renderChild(...) method as below.
    Code:
    @Overrideprotected SafeHtml renderChild(M parent, M child, int depth, TreeViewRenderMode renderMode) 
    {
        final SafeHtml safeHtml = super.renderChild(parent, child, depth, renderMode);
            
        Dto dto = (Dto) child;
        if (dto.getHighlight()) 
        {
            final SafeHtmlBuilder safeHtmlBuilder = new SafeHtmlBuilder();
                safeHtmlBuilder.appendHtmlConstant("<div style='background-color:#fae6e6'>");
                safeHtmlBuilder.append(safeHtml);
                safeHtmlBuilder.appendHtmlConstant("</div>");
                return safeHtmlBuilder.toSafeHtml();
            } 
            else 
            {
                return safeHtml;
            }
    }
    The nodes in the expanded subtree are not able to expanded.
    At the same time, when I tried to select those nodes, it appears to be not selected visually (not highlighted in blue) but in actual fact they are, when I captured the click and tree.getSelectionModel().getSelectedItem()

  7. #7
    Sencha Sr Product Manager
    Join Date
    Jan 2012
    Location
    Arlington, WA
    Posts
    1,178

    Default

    Thanks for the info, I'll investigate more shortly.

    Brandon

  8. #8
    Sencha Sr Product Manager
    Join Date
    Jan 2012
    Location
    Arlington, WA
    Posts
    1,178

    Default

    I didn't see the expansion problem yet, but I may need to try a different node to expand on. But before I do that, I thought I'd see what happens if you change the configuration so not to add another dom node to the element.

    Instead of adding a div, try adding style to the first div and does this help? I suspect adding a node is causing some other wiring to fail, but I haven't got that deep yet.

    Code:
    @Override
    protected SafeHtml renderChild(BaseDto parent, final BaseDto child, int depth, TreeViewRenderMode renderMode) {
      SafeHtml safeHtml = super.renderChild(parent, child, depth, renderMode);
     
      String s = safeHtml.asString();
      if (dto.hasHighlight()) {
        s = s.replaceFirst("<div", "<div style='background-color:#fae6e6'");
      }
      
      return SafeHtmlUtils.fromSafeConstant(s);
    }
    Would changing the configuration help?

  9. #9
    Sencha Premium Member
    Join Date
    Oct 2013
    Posts
    18

    Default

    I've tried with you suggestion. Now the behavior is as follow: (similarly with a 4-level tree)

    Issue #1
    1. Select a 2nd level node XYZ (this will programmatically expand this node, and highlight its subtree)
    2. At this point, I am able expand/collapse the 3rd level children of XYZ
    3. I left one child node (3rd level) expanded
    4. Select another 2nd level node (this is programmatically expand this node, and highlight its subtree, and collapse node XYZ, and unhighlight subtree of XYZ)
    5. Now when I expand XYZ, the 3rd level child node that was left expanded is indicated as expanded (according to the arrow indicator), but is unable to see its children nor expand/collapse it

    Issue #2
    1. Select a 2nd level node XYZ (this will programmatically expand this node, and highlight its subtree)
    2. Select one of its child node (this is suppose to expand this node and highlight its subtree, but didn't)
    3. Now the child node is unable to be expanded or selected (it is selected as indicated by tree.getSelectionModel().getSelectedItem() but not highlighted in blue visually)

  10. #10
    Sencha Sr Product Manager
    Join Date
    Jan 2012
    Location
    Arlington, WA
    Posts
    1,178

    Default

    Thanks for the details. I'll investigate this further shortly.

    Brandon

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •