treetable 공식 사이트: http://ludo.cubicphuse.nl/jquery-treetable/#api
이번 작업은 테이블 기반 트리 노드를 표시하고 편집 및 삭제 기능을 구현하는 것이었습니다. 여러 레퍼런스를 참고하여 완성했습니다.
웹 서비스 구성
노드 검색 기능이 필요하므로, 하위 노드를 조회할 때 상위 노드 데이터도 함께 반환되도록 SQL을 구성했습니다:
sql.Append("select * from(");
sql.Append(@"SELECT
row_number() OVER (ORDER BY CAST(a.SHOWINDEX AS NUMERIC(18,0)) ASC) AS rn,
a.LAID,
a.LABEL,
b.LABEL AS parent,
a.BELONINGLABLE,
a.SHOWINDEX
FROM TB_LABEL a
LEFT JOIN TB_LABEL b ON b.LAID = a.BELONINGLABLE
WHERE (
a.LABEL LIKE @bqm
OR (
SELECT COUNT(1) FROM TB_LABEL c
WHERE c.BELONINGLABLE = a.LAID AND c.LABEL LIKE @bqm
) > 0
)");
sql.Append(") t WHERE rn BETWEEN @rn1 AND @rn2");
서버 측 데이터 정렬 (부모-자식 계층 순)
조회된 List 데이터를 부모 노드가 앞에 오도록 재정렬합니다:
using System.Collections.Generic;
using System.Linq;
namespace Web
{
public static class TreeNodeHelper
{
public static List<LabelModel> SortedResult = new List<LabelModel>();
private static List<LabelModel> _sourceNodes;
public static List<LabelModel> BuildTreeList(List<LabelModel> flatList)
{
SortedResult.Clear();
_sourceNodes = flatList;
foreach (var node in _sourceNodes)
{
if (string.IsNullOrEmpty(node.ParentId))
{
SortedResult.Add(node);
AppendChildren(node);
}
}
return SortedResult;
}
private static void AppendChildren(LabelModel parent)
{
var children = GetChildNodes(parent);
foreach (var child in children)
{
SortedResult.Add(child);
AppendChildren(child);
}
}
private static List<LabelModel> GetChildNodes(LabelModel parent)
{
return _sourceNodes
.Where(n => n.ParentId == parent.Id)
.ToList();
}
}
public class LabelModel
{
public string Id { get; set; }
public string ParentId { get; set; }
public string Name { get; set; }
public string DisplayIndex { get; set; }
}
}
클라이언트 측 데이터 수신 및 테이블 생성
$.ajax({
url: WebService + "/QueryLabelData",
type: "POST",
dataType: "json",
data: '{keyword:"' + keyword + '"}',
contentType: "application/json; charset=utf-8",
success: function (response) {
var data = JSON.parse(response.d);
var rows = data.rows;
var html = '<tbody><tr><td>이름</td><td>순서</td><td>작업</td></tr>';
for (var i = 0; i < rows.length; i++) {
var item = rows[i];
var parentAttr = item.parentId ? ' data-tt-parent-id="' + item.parentId + '"' : '';
html += '<tr data-tt-id="' + item.id + '"' + parentAttr + '>' +
'<td>' + item.name + '</td>' +
'<td>' + item.displayIndex + '</td>' +
'<td>' +
'<a class="btn" onclick="editNode(\'' + item.id + '\')">수정</a>' +
'<a class="btn" onclick="deleteNode(\'' + item.id + '\')">삭제</a>' +
'</td></tr>';
}
html += '</tbody>';
$('#treeTableContainer').empty().append(html);
loadTreeResources();
}
});
테이블을 트리 형태로 변환 (리소스 동적 로딩)
var resourceLoadCount = 0;
function loadTreeResources() {
// 이전에 로드된 treetable 관련 리소스 제거
$("link[href*='treetable']").remove();
$("script[src*='treetable']").remove();
resourceLoadCount = 0;
injectResource("css/treetable/jquery.treetable.css", "css");
injectResource("css/treetable/jquery.treetable.theme.default.css", "css");
injectResource("js/treetable/jquery.treetable.js", "js");
}
function injectResource(filePath, type) {
var element;
if (type === "js") {
element = document.createElement('script');
element.src = filePath;
} else {
element = document.createElement('link');
element.rel = "stylesheet";
element.href = filePath;
}
element.onload = function() {
resourceLoadCount++;
if (resourceLoadCount === 3) {
// 이전 treetable 인스턴스 제거 후 새로 생성
$('#treeTableContainer').treetable('destroy');
$('#treeTableContainer').treetable({ expandable: true });
}
};
document.head.appendChild(element);
}
핵심 포인트: 검색 시 테이블을 다시 렌더링해야 하므로, $('#treeTableContainer').treetable('destroy')로 이전 인스턴스를 제거한 후 새로운 데이터로 초기화해야 합니다.
참고 자료:
- jQuery treetable 동적 생성 — blog.csdn.net/song_de
- JavaScript/CSS 파일 동적 로드 — blog.csdn.net/gaoqiao1988