自定义架构字段类型 运行 可以在呈现后编码吗?

Can Custom Schema Field Types Run Code After Render?

我正在尝试向我的 Apostrophe-CMS 项目添加新的架构类型。我本质上是在尝试使用 Fabric.js 添加图像设计师作为作品编辑器模态的一部分。我有一个将 Fabric.js 生成的 JSON 存储为字段的片段类型,并希望编辑器在编辑片段本身时显示在该字段的位置(或作为字段)。

我已经部分工作了(遵循 https://docs.apostrophecms.org/howtos/custom-schema-field-types.html 的指南)。但是,我 运行 遇到了一个问题。 addFieldType 的填充方法似乎在页面上呈现实际字段集之前被调用。这通常很好,因为大多数字段在呈现时都应用了基本(如果有)逻辑,但在这种情况下 Fabric.js 似乎需要 canvas 元素出现在页面上,否则它无法正确连接,无法加载。

我在第 80 行的 https://github.com/apostrophecms/apostrophe/blob/b22af9320169bf3af26cd17642373ae1e331a990/lib/modules/apostrophe-schemas/public/js/user.js 中注意到,它似乎暗示有一种方法可以覆盖自定义字段类型中的 afterPopulate。我似乎无法让它工作——我试过将它添加到 populate 中(见下文),但它从未被调用(这在查看同一文件的第 44 行时是有意义的,因为唯一的事情是在填充 fieldType 时被调用)。

有没有一种方法可以从自定义字段类型覆盖 afterPopulate,或者是否有其他方法可以处理这个问题?现在我基本上在初始化 Fabric 之前在填充中添加了 500 毫秒的超时,这确实有效,但看起来非常 hacky。这是我到目前为止添加的代码:

apos.define('fabric-editor', {

afterConstruct: function(self) {
  self.addFieldType();
},

construct: function(self, options) {

  self.addFieldType = function() {
    apos.schemas.addFieldType({
      name: 'fabric-editor',
      afterPopulate: self.afterPopulate,
      populate: self.populate,
      convert: self.convert
    });
  };

  self.afterPopulate = function($el, schema, object, callback) {
    callback();
  }

  self.populate = function(object, name, $field, $el, field, callback) {
    var $fieldset = apos.schemas.findFieldset($el, name);
    callback();
    setTimeout(function () {
        var canvas = $fieldset.find('#fabric-canvas');
        if (canvas.length > 0) {
            self.fabricCanvas = new fabric.Canvas(canvas[0]);
        }

        fabric.Object.prototype.transparentCorners = false;
        fabric.Object.prototype.cornerColor = 'blue';
        fabric.Object.prototype.cornerStyle = 'circle';
        self.addRectangle();
    }, 500)
  };

  self.addRectangle = function (ev) {
    var rect = new fabric.Rect({
        left: 10,
        top: 10,
        fill: 'red',
        width: 100,
        height: 100
    });

    self.fabricCanvas.add(rect).renderAll().setActiveObject(rect);
  }
}

});

self.afterPopulate 属于 apostrophe-schemas 模块,因此您需要在项目级 lib/modules/apostrophe-schemas/public/js/user.js 文件中覆盖它。

认为 字段的 populate 函数在字段出现在页面上之前不会被调用,但是,因为它将表单元素作为参数。