【问题标题】:Wagtail - how to get tags to work with `telepath` (tags in streamfield)?Wagtail - 如何让标签与“telepath”(流场中的标签)一起使用?
【发布时间】:2022-01-18 10:01:01
【问题描述】:

我可以在常规页面字段中使用标签,没有任何问题。在块内(流域内)使用标签时,UI 工作并且标签被保存但当前页面标签在管理中加载页面时不显示。 这是因为当前值不在模板中,而是在通过telepath 加载的 JSON 中。

我可以确认标签已保存并出现在传递给页面源中initBlockWidget 的数据中,但这些被忽略了。此外,如果我使用常规文本字段而不是标签小部件,我可以在管理员中看到保存的值。

这是我拥有的代码(在使用telepath 重构之前已经足够了)。

from wagtail.admin.widgets import AdminTagWidget

class TagBlock(TextBlock):
    @cached_property
    def field(self):
        field_kwargs = {"widget": AdminTagWidget()}
        field_kwargs.update(self.field_options)
        return forms.CharField(**field_kwargs)

我认为我需要以某种方式完成以下链接才能使其正常工作:https://docs.wagtail.io/en/stable/reference/streamfield/widget_api.html#form-widget-client-side-api

我已经试过了:

class AdminTagWidgetAdapter(WidgetAdapter):
    class Media:
        js = [
            "wagtailadmin/js/vendor/tag-it.js",
            "js/admin/admin-tag-widget-adapter.js",
        ]


register(AdminTagWidgetAdapter(), AdminTagWidget)

js/admin/admin-tag-widget-adapter.js下:

console.log("adapter"); // this shows up in the console


class BoundWidget { // copied from wagtail source code
    
    constructor(element, name, idForLabel, initialState) {
        var selector = ':input[name="' + name + '"]';
        this.input = element.find(selector).addBack(selector);  // find, including element itself
        this.idForLabel = idForLabel;
        this.setState(initialState);
    }
    getValue() {
        return this.input.val();
    }
    getState() {
        return this.input.val();
    }
    setState(state) {
        this.input.val(state);
    }
    getTextLabel(opts) {
        const val = this.getValue();
        if (typeof val !== 'string') return null;
        const maxLength = opts && opts.maxLength;
        if (maxLength && val.length > maxLength) {
            return val.substring(0, maxLength - 1) + '…';
        }
        return val;
    }
    focus() {
        this.input.focus();
    }
}

// my code here:

class AdminTagWidget {
    constructor(html, idPattern) {
        this.html = html;
        this.idPattern = idPattern;
    }

    boundWidgetClass = BoundWidget;

    render(placeholder, name, id, initialState) {
        console.log("RENDER", placeholder, name, id, initialState); // this does not show

        var html = this.html.replace(/__NAME__/g, name).replace(/__ID__/g, id);
        var idForLabel = this.idPattern.replace(/__ID__/g, id);
        var dom = $(html);
        $(placeholder).replaceWith(dom);
        // eslint-disable-next-line new-cap
        return new this.boundWidgetClass(dom, name, idForLabel, initialState);
    }
}
console.log("here") // does show in the console

// variants I've tried:
//window.telepath.register('wagtail.admin.widgets.tags.AdminTagWidget', AdminTagWidget);
//window.telepath.register('wagtail.widgets.AdminTagWidget', AdminTagWidget);
window.telepath.register('path.where.its.used.AdminTagWidget', AdminTagWidget)

我的自定义渲染方法的日志没有显示。看来我没有在window.telepath.register 中调用正确的路径,但我不知道字符串应该是什么......

我什至不确定这是否是正确的前进方向。


注意事项:

  • 它适用于常规领域,问题是关于块中的标签
  • 我使用的是 Wagtail 版本 2.13.2,但我也尝试过使用 2.15,没有任何区别。
  • 在控制台中,我可以记录 window.telepath 并查看我的自定义小部件。它只是没有“应用于”任何东西

【问题讨论】:

    标签: tags wagtail wagtail-streamfield telepath


    【解决方案1】:

    您的 WidgetAdapter 类需要一个 js_constructor 属性:

    class AdminTagWidgetAdapter(WidgetAdapter):
        js_constructor = 'myapp.widgets.AdminTagWidget'
    
        class Media:
            js = [
                "wagtailadmin/js/vendor/tag-it.js",
                "js/admin/admin-tag-widget-adapter.js",
            ]
    

    任何字符串值都可以在这里工作——它只需要唯一地标识类,所以建议使用点状模块路径以避免与其他值发生冲突。然后,这将匹配您在 Javascript 端传递给 window.telepath.register 的字符串:

    window.telepath.register('myapp.widgets.AdminTagWidget', AdminTagWidget)
    

    【讨论】:

    • 非常感谢。就在文档中间!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 2018-07-10
    • 1970-01-01
    • 2011-11-20
    • 2011-01-27
    相关资源
    最近更新 更多