【问题标题】:Custom widget using third party npm jquery module使用第三方 npm jquery 模块的自定义小部件
【发布时间】:2016-10-16 06:15:49
【问题描述】:

在从文档中进行更多研究之后,看起来自定义小部件是尝试实现我需要的最佳方式:一个自动完成下拉列表,在用户类型时按标题加载文章/博客帖子(我选择了 npm jquery -autocomplete,https://www.npmjs.com/package/jquery-autocomplete,因为我认为这个功能很容易实现,但也许 apos 本身有更简单的方法)。

我按照关于小部件的教程中的说明进行操作,http://apostrophecms.org/docs/tutorials/getting-started/custom-widgets.html,并认为我几乎已经完成了这个操作,但我没有看到呈现的搜索小部件(视图),而是 dom 显示了一个空元素 div class="apos-area" data-apos-area="" 元素,表示在将所有部分链接在一起之间缺少一块,但我无法根据文档示例代码识别缺失的部分。

这是问题 #1,下面的代码中缺少什么来阻止 search.html 视图加载?

app.js

 modules: {
    'search-widget': {}
 }

lib\modules\search-widget\index.js

module.exports = {
  extend: 'apostrophe-widgets',
  label: 'SiteSearch',
  addFields: [{
        type: 'string',
        name: 'title',
        label: 'Title'
    },
    {
        type: 'string',
        name: 'url',
        label: 'Url'
    }
  ],
  construct: function(self, options) {

    //load third party styles and scripts?
    var superPushAssets = self.pushAssets;
       self.pushAssets = function() {
       superPushAssets();
       self.pushAsset('stylesheet', 'autocomplete', { when: 'always' });
       self.pushAsset('script', 'autocomplete', { when: 'always' })
     };

    //get the data
    self.pageBeforeSend = function(req, callback) {

        var criteria = [
            { "type": "apostrophe-blog" },
            { "published": true }
        ];
        criteria = { $and: criteria };

        self.apos.docs.find(req, criteria).sort({ title: 1 }).toArray(function(err, autocomplete) {
            if (err) {
                return callback(err);
            }
            //Can I do something like this to load the widget data?
            req.data.autocomplete = autocomplete;

            return callback(null);

        });
    }
}
};

lib\modules\search-widget\views\search.html

<div id="custom-search-input">
    <div class="input-group col-md-12">
        <input type="text" class="form-control input-lg" id="site-search" placeholder="Search" />
        <span class="input-group-btn">
            <button class="btn btn-info btn-lg" type="button">
                <i class="glyphicon glyphicon-search"></i>
            </button>
       </span>
    </div>
</div>

lib\modules\撇号-pages\views\pages\home.html

  {% extends 'apostrophe-templates:layout.html' %} {% block bodyClass %}{{ super() }} home-page{% endblock %} {% block title %}Help Site: {{ data.page.title | e }}{% endblock %} {% block main %}
    <section id="promo" class="promo section offset-header">
        <div class="container text-center">
            <div class="row">
                <div class="col-md-offset-2 col-md-8 col-sm-6 col-xs-12">
                    <!--search widget-->
                    {{ apos.singleton(data.page, 'search', 'search-widget') }}
                </div>
            </div>
        </div>
    </section>

问题 #2 是,在 search-widget\index.js 构造函数中,这是加载渲染到 dom 并使用它所需的第三方资产的正确方法吗?

问题 #3 是,在 search.html 中我可以简单地使用 data.page 将数据发送到 jquery-autocomplete 对象吗?

<div id="custom-search-input">
    <div class="input-group col-md-12">
        <input type="text" class="form-control input-lg" id="site-search" placeholder="Search" />
        <span class="input-group-btn">
            <button class="btn btn-info btn-lg" type="button">
                <i class="glyphicon glyphicon-search"></i>
        </button>
    </span>
    </div>
</div>
<script>  
 $(function() {
    $("#site-search").autocomplete({
            source: {{ data.autocomplete | json }}
        }); 
  });
</script>

【问题讨论】:

    标签: apostrophe-cms


    【解决方案1】:

    如你所知,我是朋克大道 Apostrophe 团队的负责人。

    首先,提供小部件的模块的名称应以“-widgets”结尾,而不是“-widget”。它必须是复数(MAP - Modules Are Plural)。这是因为将有一个模块实例来管理小部件的所有服务器端需求(这被称为“单例模式”)。它不是“一个小部件”,而是一个管理所有此类小部件的模块。

    其次,将代码添加到pageBeforeSend,就像您现在一样,将在所有时间运行它——无论此页面是否包含小部件。从长远来看,这对于性能来说并不是最佳的。特别是因为您正在加载网站上的所有博客文章。事情会很快放缓。

    我强烈建议您查看apostrophe-twitter-widgets 模块及其源代码。除其他外,该模块实现了一个服务器端 Express 路由,专门用于向小部件提供数据,何时以及是否在页面上实际存在小部件实例并且它想知道。它还实现了一个“小部件播放器”,当页面上有此类小部件时,该方法会在浏览器端调用。

    该模块还包含一些自定义浏览器端资产并正确推送它们,这也将回答我在这个问题表面下看到的一些问题。

    但是,请注意,当它发生时,撇号已经总是将 jquery 自动完成推送到浏览器。这恰好是我们用于连接和标签的自动完成实现。因此,您无需担心推送该资产。

    您的服务器端路由应该调用autocomplete 游标过滤器,而不是一直获取世界上的一切。 (: Apostrophe 大量使用自动完成功能,因此它已经为以智能且实现良好的方式获取与前缀匹配的内容提供了便利。

    如果您不清楚光标过滤器,请务必阅读有关使用模型层的 HOWTO。

    另外,请始终使用相应模块的 find 方法,不要重新发明它,并尝试自己找出适合返回博客文章的原因。

    您的路线可能如下所示:

    // Inside the construct function of your module...
    
    self.route('get', 'autocomplete', function(req, res) {
      return self.apos.docs.getManager('apostrophe-blog')
        .find()
        .autocomplete(req.query.term)
        .limit(10)
        .projection({
          areas: false,
          joins: false
        })
        .toArray(function(err, posts) {
          if (err) {
            res.statusCode = 500;
            return res.send('error');
          }
          return res.send(_.map(posts, function(post) {
            return {
              value: post._url,
              label: post.title
            }
          }));
        }
      );
    });
    

    这将进入模块的 construct 函数中。

    现在有一个 GET 方法 Express 路由在 /modules/search-widgets/autocomplete 等待您的来信。通过在浏览器端编写一个播放器方法来完成这项工作。您可以在apostrophe-twitter-widgets 代码中查看它们的外观以及将它们放在何处。当然,您的会在您的小部件模板中的文本输入字段上调用.autocomplete()。它会将 jquery 自动完成 source 选项设置为 /modules/search-widgets/autocomplete

    希望对您有所帮助!

    【讨论】:

      猜你喜欢
      • 2020-05-22
      • 2018-11-02
      • 2016-08-01
      • 1970-01-01
      • 2012-02-28
      • 2021-03-13
      • 2017-04-14
      • 2015-01-25
      • 1970-01-01
      相关资源
      最近更新 更多