曦远 (DealiAxy)一份私人的文字刊物

StarBlog
返回文章列表折页手记阅读全文
Web前端

I modded the bootstrap-treeview component a bit and published an NPM package to try it out

Preface In a previous article, Building a Blog Project Based on .NetCore StarBlog - (8) Displaying Hierarchical Categories, I mentioned that to make the article category list support a hierarchical structure, I used a tree component. However, this component is too old—the Bootstrap version it uses is actually 3.x—but I couldn't find anything better, so I had to grit my teeth and use it. But I was unhappy with a lot of the actual results. The original author had simply given up and marked the project as Archived on GitHub. Nothing I could do. Thanks to open source, I just forked a copy of the code to

曦远 (DealiAxy)约 16 分钟
目录8 个章节

Preface

In a previous article Building a Blog Project Based on .NetCore StarBlog - (8) Displaying Hierarchical Categories, I mentioned that to make the article category list support a hierarchical structure, I used a tree component. However, this component is too old—the Bootstrap version it uses is actually 3.x—but I couldn't find anything better, so I had to grit my teeth and use it.

But I was unhappy with a lot of the actual results. The original author had simply given up and marked the project as Archived on GitHub. Nothing I could do.

Thanks to open source, I just forked a copy of the code and hacked it to get the effect I wanted~

Then I even uploaded it to npm~ (first time publishing a package on npm)

If you need it, you can try installing it:

npm i bootstrap5-treeview

The Result

I'll put the pictures first, then talk about what I changed

image-20220527225742322

Layout Changes

I noticed that the original version wraps tags as a badge and puts them directly after the text. Not sure if it's because Bootstrap changed, but on the current 5.x version they look cramped together, and there's no color either, because the original author only added the badge class.

I went straight into the JS code, found the badge definition, and modified it!

Tree.prototype.template = {
    // ...
    badge: '<span class="ms-1 badge bg-primary rounded-pill"></span>'
};

Added a background color and rounded corners, and it looks much better~

Then! The cramped-together problem still wasn't solved. The original implementation rendered HTML roughly like this

<ul class="list-group">
  <li class="list-group-item">An item</li>
  <li class="list-group-item">A second item</li>
  <li class="list-group-item">A third item</li>
  <li class="list-group-item">A fourth item</li>
  <li class="list-group-item">And a fifth one</li>
</ul>

Ideally they'd be distributed on both sides, which flex layout is perfect for. The rendered result should be something like this

<ol class="list-group">
  <li class="list-group-item d-flex justify-content-between align-items-start">
    <div>Subheading</div>
    <span class="badge bg-primary rounded-pill">tag</span>
  </li>
</ol>

But originally this component appended every element one by one into the list-group-item, which made the result look ugly

No problem, I've got the code, let's change it!

First, redefine a few element templates

Including the badge above, here are all the element templates

Tree.prototype.template = {
    list: '<ul class="list-group"></ul>',
    itemWrapper: '<li class="list-group-item d-flex justify-content-between align-items-start"></li>',
    itemLeftElem: '<div class="w-100"></div>',
    itemRightElem: '<div></div>',
    indent: '<span class="mx-2"></span>',
    icon: '<span class="icon"></span>',
    link: '<a class="w-75" href="#" style="display:inline-block; color:inherit; text-decoration:none;"></a>',
    badge: '<span class="ms-1 badge bg-primary rounded-pill"></span>'
};

Then find the code that assembles the list item elements

In Tree.prototype.buildTree, there's a $.each(nodes, function addNodes(id, node) loop body

Just change the code

// 最外层包装
let treeItem = $(_this.template.itemWrapper)
.addClass('node-' + _this.elementId)
.addClass(node.state.checked ? 'node-checked' : '')
.addClass(node.state.disabled ? 'node-disabled' : '')
.addClass(node.state.selected ? 'node-selected' : '')
.addClass(node.searchResult ? 'search-result' : '')
.attr('data-nodeid', node.nodeId)
.attr('style', _this.buildStyleOverride(node));

// item 内分成两个元素,用flex布局分布在左右两边
let treeItemLeft = $(_this.template.itemLeftElem)
let treeItemRight = $(_this.template.itemRightElem)
treeItem.append(treeItemLeft)
treeItem.append(treeItemRight)

Then change the tag rendering code to this

// Add tags as badges
if (_this.options.showTags && node.tags) {
    $.each(node.tags, function addTag(id, tag) {
        treeItemRight.append(
            $(_this.template.badge).append(tag)
        );
    });
}

Append all other elements under the treeItemLeft element

Adding Indent Control

The original version had no way to control whether submenu indent is enabled; it was on by default. I added an option to control enabling it

_default.settings = {
    // ...
    enableIndent: true, // 添加了控制是否启用缩进的开关
}

Then still in that $.each(nodes, function addNodes(id, node) loop above, just add a condition and it's done

// Add indent/spacer to mimic tree structure
// 添加了控制是否启用缩进的开关
if (_this.options.enableIndent) {
    for (let i = 0; i < (level - 1); i++) {
        treeItemLeft.append(_this.template.indent);
    }
}

Publishing to NPM

First time publishing a package on NPM, (I guess that counts as contributing to the open source community)

I referred to this article: https://segmentfault.com/a/1190000013940567

First register an account on the NPM website, then log in locally with npm login

Once that's done, run npm publish in the project root directory and you're good

Of course this is a fork, so I had to change the info in package.json, otherwise it would conflict with the original author's package and couldn't be uploaded.

Summary

The barrier to modding frontend components and publishing to NPM is really low. It reminded me of my previous experience publishing Python packages on pip—similar operations, one-click submit, and you're off~

But by comparison, NPM is even a bit easier than pip. At least I didn't run into any obstacles, and didn't need to install anything extra to get it done

(The only obstacle was that this package's dependencies are too old. I couldn't install the ancient version of grunt; later I installed a newer version and then I could run the tasks)

Code

Full code on GitHub: https://github.com/Deali-Axy/bootstrap5-treeview

And the NPM page: https://www.npmjs.com/package/bootstrap5-treeview

If you need to implement a tree structure, give it a try—I think it's pretty decent~

References

_EOF_

I modded the bootstrap-treeview component a bit and published an NPM package to try it out

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…