在dataviewjs中,根据yaml属性实时筛选文档

一、前置条件

  1. 安装dataview插件
  2. 安装template插件
  3. 安装button插件

二、源代码

在dataviewjs中,输入以下代码

const {createButton} = app.plugins.plugins["buttons"]
const tp = app.plugins.plugins["templater-obsidian"].templater.current_functions_object

let current = dv.current()
let currentFile = app.vault.getAbstractFileByPath(current.file.path)

const changeFilter = async(prop) => {
  let propName = "filter-" + prop
  let values = pages.map(p => p[prop])
  values = [...new Set(values)]
  values.unshift("all") // Removed "clear" option

  let val = await tp.system.suggester(values, values)
  
  app.fileManager.processFrontMatter(currentFile, (frontmatter) => { 
    frontmatter[propName] = val; // Directly set the value
  })
}

const filterButton = async(name, prop) => {
  createButton({
    app, 
    el: this.container, 
    args: {
      name: name}, 
    clickOverride: {
      click: () => changeFilter(prop), 
      params: [prop]
    }
  })
}

// Reset button function
const resetFilters = async() => {
  app.fileManager.processFrontMatter(currentFile, (frontmatter) => {
    Object.keys(frontmatter).forEach(key => {
      if (key.startsWith("filter-")) {
        delete frontmatter[key];
      }
    });
  })
}

const resetButton = async(name) => {
  createButton({
    app, 
    el: this.container, 
    args: {
      name: name}, 
    clickOverride: {
      click: () => resetFilters(), 
      params: []
    }
  })
}

let pages = dv.pages('"请输入要查找的文件夹路径"')
let filteredPages = [...pages]

// Apply filters
let colorFilter = current["filter-color"]
let numberFilter = current["filter-number"]

if (colorFilter != "all" && colorFilter != null) {
  filteredPages = filteredPages.filter(p => p.color == colorFilter)
}

if (numberFilter != "all" && numberFilter != null) {
  filteredPages = filteredPages.filter(p => p.number == numberFilter)
}

// Add filter buttons
await filterButton("Filter color", "color")
await filterButton("Filter number", "number")

// Add reset button
await resetButton("Reset")

let headers = ["Name", "Color", "Number"]
let rows = filteredPages.map(p => [p.file.link, p.color, p.number])

dv.table(headers, rows)

测试文档E3的YAML

---
color: green
number: "3"
---

三、使用效果
动画

四、主要缺陷

  1. 只能筛选类型为文本和数字的属性,如果有人愿意优化,让它能筛选标签、列表、复选框、日期和时间就更好了。(参考来源的链接好像能实现,但是研究半天,还是实现不了,只有这个简易版的成功了,如果有更好用的属性筛选,希望大家能多多分享)
  2. 筛选有点卡顿。

五、参考来源

1 个赞

这个代码之前坛里有人发过:【已解决】我想创建一个过滤属性表,点击按钮便可以筛选出不同来源的文章 - #2,来自 Cora

对应的优化是:DataviewJS 下拉筛选菜单搜索功能

供参考。