Wigtail:如何定义自定义块的js_initializer以便子块的js_initializers也运行?

时间:2017-12-08 19:42:43

标签: python wagtail wagtail-streamfield

我最初在wagtail问题队列中问了这个问题,我猜这是错误的地方。 (虽然我认为这是documentation中的一个错误。)

无论如何,我的问题是我有一个自定义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"))
},

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

1 个答案:

答案 0 :(得分:2)

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

每当一个块作为其他块的包装器时,就像StructBlock那样,它负责确保为其子块强制执行此契约:当在页面加载时评估其自己的js_initializer时,子{{ 1}}也需要在那时进行评估,并且当调用其初始化函数时,它会调用这些子初始化函数。

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

图像gallery.js:

js_initializer

my_blocks.py:

/* 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();
    };
}