2

我得到了这个模板(默认)

<span class="x-legend-item-marker {[values.disabled?'x-legend-inactive':'']}" style="background:{mark};"></span>{name}

产生这个:

在此处输入图像描述

我想拥有与它的每一个功能相同的模板。但是,我还需要一个 if 子句。如果一个项目的值为 0,我不希望它被“传奇化”。

这是完整的代码

{
xtype: 'container',
                title: 'Chart',
                iconCls: 'chart',
                itemId: 'chart_Tab',
                layout: {
                    type: 'fit'
                },
                items: [
                    {
                        xtype: 'polar',
                        itemId: 'pie',
                        colors: [
                            '#115fa6',
                            '#94ae0a',
                            '#a61120',
                            '#ff8809',
                            '#ffd13e',
                            '#a61187',
                            '#24ad9a',
                            '#7c7474',
                            '#a66111',
                            '#222222',
                            '#115ea6',
                            '#94cc0a',
                            '#b61120',
                            '#dd8809',
                            '#11d13e',
                            '#a68887',
                            '#94df9d',
                            '#7f74f4',
                            '#112341',
                            '#abcdef1'
                        ],
                        store: 'relativedata',
                        series: [
                            {
                                type: 'pie',
                                label: {
                                    textBaseline: 'middle',
                                    textAlign: 'center',
                                    font: '9px Helvetica'
                                },
                                labelField: 'strName',
                                labelOverflowPadding: 0,
                                xField: 'numValue'
                            }
                        ],
                        interactions: [
                            {
                                type: 'rotate'
                            }
                        ],
                        listeners: [
                            {
                                fn: function(element, eOpts) {
                                    var relStore = Ext.getStore('relativedata');
                                    var eleStore = Ext.getStore('element');
                                    var relModel;
                                    var eleModel;

                                    relStore.removeAll();

                                    //Convert to CO2 qty
                                    for(var i = 0; i< eleStore.getCount();i++)
                                    {
                                        eleModel = eleStore.getAt(i);
                                        relModel = Ext.create(APPNAME + '.model.RelativeElement');
                                        relModel.set('strName',eleModel.get('strName'));
                                        relModel.set('numValue', eleModel.get('numValue')*eleModel.getFactor());
                                        relStore.add(relModel);
                                    }

                                    relStore.sync();

                                    //Hide arrows-legend
                                    this._series[0]._label.attr.hidden=true;
                                },
                                event: 'painted'
                            }
                        ],
                        legend: {
                            xtype: 'legend',
                            docked: 'bottom',
                            itemId: 'pie_legend',
                            itemTpl: [
                                '<span class="x-legend-item-marker {[values.disabled?\'x-legend-inactive\':\'\']}" style="background:{mark};"></span>{name}'
                            ],
                            maxItemCache: 100,
                            store: 'element'
                        }
                    }
                ]
            }

我寻求帮助是因为我对模板不太擅长。我不敢说我​​实际上了解默认的一切。

4

1 回答 1

3

我回来了!然而,没有人因此而称我为苗条的黑幕……不幸的是!

因此,要回答您最初的问题,您需要的模板如下所示:

// Configuration of the chart legend
legend: {
    // Finally, we can use the value field to customize our templates.
    itemTpl: [
        '<tpl if="value != 0">', // <= template condition
            '<span class="x-legend-item-marker {[values.disabled?\'x-legend-inactive\':\'\']}" style="background:{mark};"></span>{name}',
        '</tpl>'
    ]
    // ...
}

不幸的是,正如我在之前的评论中所说,快速调试器检查表明,value在应用此模板时,此变量或任何等效项不可用。

现在我将详细解释我是如何克服这种烦恼的。部分是因为这是一个如此复杂的黑客,如果你决定应用它,你最好知道你在做什么,部分是因为你会通过亲眼目睹钓鱼技术学到更多的东西,而不是被赋予正确的鱼离开——在这种情况下,鱼无论如何都不能零售。而且在很大程度上,我必须承认,因为我喜欢对我投入了一些精力的事情进行抒情,而且已经很晚了,我对自我祝贺的防御变得有点弱......

因此,查看Ext.chart.Legend's 的代码表明那里没有什么可做的,它只是Ext.dataview.Dataview. 因此,它必须有一个绑定到它的存储,显然(不幸的是)它不是绑定到图表以提供其数据的存储。

另一个明智的断点(在Legend's方法中)表明这个storesetStore来自,即。Ext.chart.AbstractChartprovideLegendInfo

我们越来越接近我们的目标。我们需要做的是向图例存储添加一个值字段,并让我们的系列为该字段提供数据。伟大的!

现在明智的方法是用最少量的 Ext 代码复制来实现这些修改......但是在花了很多时间试图做到这一点但没有运气之后,我将满足于疯狂地覆盖这两种方法, 并建议放一个大粗体警告以检查这些方法的代码是否不会随着 Touch 的下一个版本而改变:

if (Ext.getVersion().isGreaterThan('2.2.1')) {
    // Give yourself a big warning to check that the overridden methods' code
    // bellow has not changed (see further comments).
}

有了这些,让我们直奔主题,不再考虑后代。

也就是说,首先我们在图例存储中添加一个值字段:

/**
 * Adds a value field to legend store.
 */
Ext.define(null, {
    override: 'Ext.chart.AbstractChart'
    // Berk, what a lot of code replication :( Let's just hope that this method's code
    // won't change in the future...
    ,constructor: function() {
        var me = this;
        me.itemListeners = {};
        me.surfaceMap = {};
        me.legendStore = new Ext.data.Store({
            storeId: this.getId() + '-legendStore',
            autoDestroy: true,
            fields: [
                'id', 'name', 'mark', 'disabled', 'series', 'index'
                // Adding my value field
                ,'value'
            ]
        });
        me.suspendLayout();

        // For whatever reason, AbstractChart doesn't want to call its superclass
        // (Ext.draw.Component) constructor and, by using callSuper, skips directly to
        // Ext.Container's one. So well... I respect, but I must do it old school since
        // callSuper would go to Ext.draw.Component from here.
        Ext.Container.prototype.constructor.apply(this, arguments);
        // me.callSuper(arguments);

        me.refreshLegendStore();
        me.getLegendStore().on('updaterecord', 'onUpdateLegendStore', me);
        me.resumeLayout();
    }
}, function() {
    // Post-create functions are not called for overrides in touch as they are 
    // in ExtJS? Hmm... That would have been the perfect place to issue a big
    //  warning in case the version has changed, but we'll live with it :(
});

其次,我们让我们的图表系列提供该值。从您的代码中,我可以推断出您正在使用饼图,所以我只是给出代码,作为说明......但是,如果您一直遵循到这里,它应该是微不足道的为其他类型的系列实现它。无论如何,这是代码:

/**
 * Overrides `provideLegendInfo` to add the value to the legend records.
 *
 * Here again, let us all cross our fingers very hard, hoping for Sencha's team to not decide
 * to add their own extra fields too soon...
 */
Ext.define(null, {
    override: 'Ext.chart.series.Pie'
    ,provideLegendInfo: function(target) {
        var store = this.getStore();
        if (store) {
            var items = store.getData().items,
                labelField = this.getLabelField(),
                field = this.getField(),
                hidden = this.getHidden();
            for (var i = 0; i < items.length; i++) {
                target.push({
                    name: labelField ? String(items[i].get(labelField))  : field + " " + i,
                    mark: this.getStyleByIndex(i).fillStyle || this.getStyleByIndex(i).strokeStyle || 'black',
                    disabled: hidden[i],
                    series: this.getId(),
                    index: i
                    // Providing actual data value to the legend record
                    ,value: items[i].get(field)
                });
            }
        }
    }
});

让我们总结一下。我们有两个覆盖和一个自定义模板。我们可以希望我们现在已经完成了。但这是我们得到的:

没有 CSS 的空系列

因此,在's 标记DataView周围添加了一些自己的标记。itemTpl好吧,好吧,好吧……在这一点上,我已经厌倦了跟踪 Ext 的内部结构,幸运的是(这一次!),我设想了一个快速补丁。因此,我毫不犹豫地将这条 CSS 规则放入:

.x-legend-item:empty {
    display: none;
}

最后我们完成了。我想我的思路和代码可能有点难以复制,所以让我为您提供一个明确的证据,证明这一切都有效。

在这个演示中,有一个值为 0 的“公制四”。

{
    'name': 'metric four',
    'data': 0
}

但你不会看到它。因为这就是这一切的重点,不是吗?

于 2013-07-31T00:57:39.550 回答