I have a table in database like this:
id - title - parentID
-----------------------------
1 Root null
2 item 1 1
3 item 2 1
4 item 3 1
5 item 3.1 4
this should create something like this:
--Root
----item 1
----item 2
----item 3
-------item 3.1
here's my controller to fetch the root node and its children:
@RequestMapping(value="/CourtBranch/LoadTreeView", method = RequestMethod.GET)
public void LoadList(@RequestParam("ParentId") String parentID,HttpServletRequest req, HttpServletResponse resp) {
List lst;
if (parentID.equals("Root"))
{
lst = _COURTBRANCH.LoadTreeChildren(null, "Root"); // selects records which have parent=null
}
else
{
lst = _COURTBRANCH.LoadTreeChildren(parentID, "TreeNode"); // selects records which have parent=parentID
}
resp.setContentType("application/json");
resp.setCharacterEncoding("utf-8");
try {
resp.getWriter().print(_gson.toJson(lst));
} catch (IOException e) {
e.printStackTrace();
}
}
and this script loads my root:
<script type="text/javascript">
$(function(){
$("#tree").dynatree({
initAjax: {
url: "/CourtBranch/LoadTreeView.json?ParentId=Root",
data: { mode: "funnyMode" }
},
onActivate: function(node) {
$("#echoActive").text(node.data.title);
},
onDeactivate: function(node) {
$("#echoActive").text("-");
}
});
});
</script>
now I need to know how to send the root's id to my controller to fetch root's children and add them to the root node. should I use appendAjax function? how?
Basically you don't really want to do that straight into your controller. (loose coupling)
I'd create 2 utils classes Tree<T>
and Node<T>
to manage your tree and nodes:
Here is the tree class:
public class Tree<T> {
private Node<T> rootElement;
public Tree() {
super();
}
public Node<T> getRootElement() {
return this.rootElement;
}
public void setRootElement(final Node<T> rootElement) {
this.rootElement = rootElement;
}
public List<Node<T>> toList() {
final List<Node<T>> list = new ArrayList<Node<T>>();
walk(this.rootElement, list);
return list;
}
private void walk(final Node<T> element, final List<Node<T>> list) {
list.add(element);
for (final Node<T> data : element.getChildren()) {
walk(data, list);
}
}
}
And the node class with some helper methods
public class Node<T> {
private T data;
private List<Node<T>> children;
public Node() {
super();
}
public Node(final T data) {
this();
setData(data);
}
public Boolean hasChildren() {
return this.children.size() != 0;
}
public List<Node<T>> getChildren() {
if (this.children == null) {
return new ArrayList<Node<T>>();
}
return this.children;
}
public void setChildren(final List<Node<T>> children) {
this.children = children;
}
public int getNumberOfChildren() {
return this.children.size();
}
public void addChild(final Node<T> child) {
if (this.children == null) {
this.children = new ArrayList<Node<T>>();
}
this.children.add(child);
}
public void insertChildAt(final int index, final Node<T> child) throws IndexOutOfBoundsException {
if (index == getNumberOfChildren()) {
addChild(child);
return;
} else {
this.children.get(index);
this.children.add(index, child);
}
}
public void removeChildAt(final int index) throws IndexOutOfBoundsException {
this.children.remove(index);
}
public T getData() {
return this.data;
}
public void setData(final T data) {
this.data = data;
}
}
Then I'd have your type of tree extending the tree. based on your controller CourtBranch
Suppose your CourtBranch model has the following structure (I'm using hibernate + jpa):
@Entity
@Table
public class CourtBranch
private String id;
private String name;
private Long partentId;
//getters setters etc...
Create a class that extends the Tree:
public class CourtBranchTree extends Tree<CourtBranch>
public CourtBranchTree{
super();
}
Now create your TreeGridResponse class:
public class TreeGridResponse {
//inject the service to get the id of your model
@Resource
CourtBranchService cbService;
//if you are using a repository for the db queries:
@Resource
CourtBranchRepository cbRepo;
public TreeGridResponse(){
}
//returning the tree as a JSON to use AJAX
public String cbBTreeAsJson(final CourtBranchTree tree){
final StringBuffer sb = new StringBuffer();
final CourtBranch root = tree.getRootElement().getData();
sb.append("[\r {\"title\": \"" + root.getName() + "\", \"key\": \"" + root.getId() + "\", \"children\": [\r");
final List<Node<CourtBranch>> children = tree.getRootElement().getChildren();
loopforChildre(sb, children);
sb.append("]");
return sb.toString();
}
private StringBuffer loopForChildren(final StringBuffer sb, final List<Node<UserRight>> children) {
for (int i = 0; i < children.size(); i++) {
final Node<courtBranch> childElement = children.get(i);
if (i == 0) {
sb.append("{\"title\": \"" + childElement.getData().getName() + "\", \"key\": \"" + childElement.getData().getId() + "\"");
} else {
sb.append(", {\"title\": \"" + childElement.getData().getName() + "\", \"key\": \"" + childElement.getData().getId() + "\"");
}
if (childElement.hasChildren()) {
sb.append(", \"children\": [\r");
loopForChildren(sb, childElement.getChildren());
} else {
sb.append("}");
}
}
sb.append("]}");
return sb;
}
public CourtBranchTree get() {
final CourtBranchTreetree tree = new CourtBranchTree();
final Node<CourtBranch> root = new Node<CourtBranch> (this.cbRepo.findOne(Long.valueOf(1)));//gets your root
getRecursive(root, tree);
tree.setRootElement(root);
return tree;
}
private void getRecursive(final Node<CourtBranch> courtBranch, final CourtBranchTree tree) {
final List<CourtBranch> children = this.cbService.findCourtBranchByParentId(courtBranch.getData().getId());
final List<Node<CourtBranch>> childElements = new ArrayList<Node<CourtBranch>>();
for (final CourtBranch childCourtBranch : children) {
final Node<CourtBranch> childElement = new Node<CourtBranch>(childUserRight);
childElements.add(childElement);
getRecursive(childElement, tree);
}
courtBranch.setChildren(childElements);
}
}
Register the TreeGridResponse in your config to get the bean and inject it into your controller.
@Controller
public class CBController
@Resource
private TreeGridResponse gridResponse;
@RequestMapping(value="/CourtBranch/LoadTreeView", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String cbTree() {
return this.gridResponse.cbBTreeAsJson(this.gridResponse.get());
}
Note the @ResponseBody annotation that will indicate Spring to parse your string into JSON so that your AJAX can read it.
And your jsp:
<div id ="cbTree"></div>
<script type ="text/javascript">
$(function(){
$("#cbTree").dynatree({
initAjax:{
url: /CourtBranch/LoadTreeView
},
checkbox: true,
selectMode: 3
});
});
</script>
Hope this helped...