Wagtail - 如何让标签与“telepath”(streamfield 中的标签)一起使用?
Wagtail - how to get tags to work with `telepath` (tags in streamfield)?
我可以在常规页面字段中使用标签,没有任何问题。当在块内(在流场内)使用标签时,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)
我认为以下 link 是我需要以某种方式完成才能使其正常工作的内容: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 并查看我的自定义小部件。它只是没有“应用”到任何东西
您的 WidgetAdapter
class 需要一个 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",
]
任何字符串值都可以在这里使用 - 它只需要唯一标识 class,因此建议使用点状模块式路径以避免与其他路径冲突。这然后匹配您传递给 Javascript 侧的 window.telepath.register
的字符串:
window.telepath.register('myapp.widgets.AdminTagWidget', AdminTagWidget)
我可以在常规页面字段中使用标签,没有任何问题。当在块内(在流场内)使用标签时,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)
我认为以下 link 是我需要以某种方式完成才能使其正常工作的内容: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 并查看我的自定义小部件。它只是没有“应用”到任何东西
您的 WidgetAdapter
class 需要一个 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",
]
任何字符串值都可以在这里使用 - 它只需要唯一标识 class,因此建议使用点状模块式路径以避免与其他路径冲突。这然后匹配您传递给 Javascript 侧的 window.telepath.register
的字符串:
window.telepath.register('myapp.widgets.AdminTagWidget', AdminTagWidget)