d3有条件地添加数据属性

时间:2013-08-13 09:12:17

标签: d3.js

我正在创建一个d3表,供FooTable jquery plugin使用,这需要在标题行中包含一些数据属性。但并非所有列都具有所有数据属性,并且想知道是否有办法执行此操作。

这种方法有点工作,通过添加所有可能的数据属性并留下一些空白,但我确信这不是好的做法。

var th = d3.select(selection).select("thead").selectAll("th")
            .data(colspec)
            .enter().append("th")
            .text(function(d) { return d["data-name"]; })
            .attr("data-class", function(d) {
                if ("data-class" in d) {
                    return d["data-class"];
                } else {
                    return "";
                }
            })
            .attr("data-hide", function(d) {
                if ("data-hide" in d) {
                    return d["data-hide"];
                } else {
                    return "";
                }
            })
            .attr("data-ignore", function(d) {
                if ("data-ignore" in d) {
                    return d["data-ignore"];
                } else {
                    return "";
                }
            })

       etc.

colspec例子:

[{"data-name": "username"}, {"data-name": "Date Joined", "data-hide": "true"}]

目前正在:

  <th data-class="" data-hide="true" data-ignore="" data-type="">Joined</th>

   <th  data-hide="true" >Joined</th>

有什么建议吗?

5 个答案:

答案 0 :(得分:54)

您不需要调用each()或filter()... attr()函数将在内部为您执行此操作。只需用函数而不是值来调用它,并让该函数返回每个数据的所需值,如果特定数据不需要该属性,则返回null,如下所示:

...
.attr('data-class', function(d) {
    return 'data-class' in d ? d['data-class'] : null;
});

如果函数返回null,则不添加该属性。您甚至可以通过向函数提供attr名称映射来将多个属性组合到一个调用中:

...
.attr({
    'data-class': function(d) {
        return 'data-class' in d ? d['data-class'] : null;
    }, 
    'data-hide': function(d) {
        return 'data-hide' in d ? d['data-hide'] : null;
    },
    'data-ignore': function(d) {
        return 'data-ignore' in d ? d['data-ignore'] : null;
    }
});

或者如果您喜欢我并且不想输入那么多,您可以将属性名称列表缩减到相应的地图中:

...
.attr(['data-class', 'data-hide', 'data-ignore'].reduce(function(result, attr) {
    result[attr] = function(d) {
        return attr in d ? d[attr] : null;
    }
    return result;
}, {}));

答案 1 :(得分:31)

似乎是.each()的好候选人:

var th = d3.select(selection).select("thead").selectAll("th")
        .data(colspec)
    .enter().append("th")
        .text(function(d) { return d["data-name"]; })
        // now address each item individually
        .each(function(d) {
            var header = d3.select(this);
            // loop through the keys - this assumes no extra data
            d3.keys(d).forEach(function(key) {
                if (key != "data-name")
                    header.attr(key, d[key]);
            });
        });

我经常使用.each,因为每个项目范围比尝试为每个项目找出一堆属性更有意义。

对于一个简短的属性列表,特别是如果您担心对象中的额外数据,可能更容易遍历所需的键而不是所有内容:

        .each(function(d) {
            var header = d3.select(this);
            ['data-class', 'data-hide', 'data-ignore'].forEach(function(key) {
                if (key in d)
                    header.attr(key, d[key]);
            });
        });

答案 2 :(得分:6)

您可以使用.filter()功能仅对您需要设置属性的选项子集进行操作,例如

var th = d3.select(selection).select("thead").selectAll("th")
        .data(colspec)
        .enter().append("th")
        .text(function(d) { return d["data-name"]; });
th.filter(function(d) { return ("data-class" in d); })
        .attr("data-class", function(d) {
            return d["data-class"];
        });

答案 3 :(得分:0)

更清洁的是使用过滤器

.filter(d => !!d["data-class"]) // filter only data with the "data-class" property
.attr("data-class", d => d["data-class"])

答案 4 :(得分:0)

投票最多的解决方案是完美的,因为.attr(a,b)为空时,b是有条件的,

 d3chain.attr('data-class', d=>'data-class' in d ? d['data-class'] : null );

但该解决方案不是通用的,对于其他链接方法无效,除非使用.each().filter.call()。通常,最简单的是call()

.call(condFunc,param)

假设param是用作条件中参数的全局变量,而g是用于返回值的全局对象。

  // inconditional
  d3chain.attr(param, g[param])

  // conditional case using globals
  d3chain.call( s => { if (g[param]) s.attr(param,g[param]) })

  // conditional case passing the parameter
  d3chain.call( (s,p) => {
     if (g[p]) s.attr(p, g[p])
  }, param)

.each(d => condFunc)

典型用途:

 d3chain.each( d=> {
     if (param && d) d3.select(this).attr(d, g[param])
 })

有关详细示例,请参见@nrabinowitz答案。

.filter(d => condFunc).etc

典型用途:

 d3chain.filter( d=> param in d ).attr(param, d=> g[param])

有关详细示例,请参见@LarsKotthoff答案。