0

我最初在 wagtail 问题队列上问了这个问题,我想这是错误的地方。(虽然我确实认为这是文档中的一个错误。)

无论如何,我的问题是我有一个在StructBlock其中使用的自定义类ListBlock。我需要js_initializer()在我的自定义类上定义一个方法,该方法会导致表单同时触发我自己的初始化程序 ListBlock的初始化程序。

我最初的尝试,基于docs,看起来像这样:

# my_blocks.py
class ImageGalleryBlock(blocks.StructBlock):
    images = ListBlock(ImageChooserBlock(label='Image'))

    def js_initializer(self):
        return "ImageGallery"

    @property
    def media(self):
        return forms.Media(
            js=['app/js/admin/image-gallery.js']
        )


# image-gallery.js
function ImageGallery(prefix) {
    // Set up the Image Gallery block's custom form behavior...
}

这使ImageGallery()函数运行,但没有运行ListBlock的初始化程序,所以它的按钮都不起作用。

在 wagtail 问题队列中,建议我尝试这样的事情:

def js_initializer(self):
    initializer_js = super(HeadingBlock, self).js_initializer()
    my_custom_js = 'ImageGallery("%s")' % self.definition_prefix
    if initializer_js:
        # child blocks have custom JS initializers and need to be used
        return '%s,\n%s' % (initializer_js, my_custom_js)
    return my_custom_js

# image-gallery.js
function ImageGallery(prefix) {
  var init_image_gallery = function(element_prefix) {
    // Do stuff...
  };

  return init_image_gallery;
}

我必须对最初的建议进行一些改进才能使该ImageGallery()部件发挥作用,但它仍然没有运行ListBlock初始化程序。

以下是为其生成的初始化程序代码的ImageGalleryBlock样子:

{
    'name': ('ImageGalleryBlock'),
    'initializer': (StructBlock({
        'images': (ListBlock({
            'definitionPrefix': ('blockdef-63')
        }))
    }),
    ImageGallery("blockdef-91"))
},

我觉得我真正需要做的是为正在传递的 dict 添加另一个键StructBlock,但我没有最模糊的线索。

4

1 回答 1

2

一个js_initializer方法返回一个 Javascript 表达式,该表达式在页面加载时被评估一次,并输出一个函数;然后,每次将块插入表单时都会调用此初始化函数,并传递 ID 前缀以标识应接收 Javascript 行为的 HTML 元素。重要的是要理解这是一个两步过程 - 页面加载的初始评估(通常采用函数调用的形式,返回要在第二步中使用的函数),并为每个块调用初始化函数表格。

每当一个块充当其他块的包装器时,就像 StructBlock 所做的那样,它负责确保对其子块执行此合同:当js_initializer在页面加载时评估它自己的时,也js_initializer需要评估子块,当它的初始化函数被调用时,它会调用那些子初始化函数。

通过继承 StructBlock 和覆盖js_initializer,您实际上是在 StructBlock 周围添加了另一层包装:您的新js_initializer需要评估为一个函数,该函数既调用 StructBlock 的初始化函数,又执行您的自定义图像库设置。以下是如何做到这一点:

图片库.js:

/* ImageGallery gets called once on startup; the function it returns will
be called whenever we need to set up an image gallery block on the form */
function ImageGallery(parentInitializer) {
    return function(elementPrefix) {
        /* call the original StructBlock initializer */
        parentInitializer(elementPrefix);

        /* do whatever JS setup you need for the image gallery behaviour */
        $('#' + elementPrefix + '-gallery').doStuff();
    };
}

my_blocks.py:

class ImageGalleryBlock(blocks.StructBlock):
    images = ListBlock(ImageChooserBlock(label='Image'))

    def js_initializer(self):
        parent_initializer = super(ImageGalleryBlock, self).js_initializer()
        return "ImageGallery(%s)" % parent_initializer

    @property
    def media(self):
        # need to pull in StructBlock's own js code as well as our own
        return super(ImageGalleryBlock, self).media + forms.Media(
            js=['app/js/admin/image-gallery.js']
        )
于 2017-12-10T21:39:09.750 回答