【问题标题】:Virtual "name" field?虚拟“名称”字段?
【发布时间】:2017-03-11 21:00:00
【问题描述】:

我需要让模型的名称字段是虚拟的,通过将两个真实字段连接在一起来创建。此名称仅供显示。我已经尝试过文档中的虚拟示例,但没有运气。 Keystone 4 beta5。

var keystone = require('keystone')
    _ = require('underscore');
var Types = keystone.Field.Types;

/**
 * Foo Model
 * ==================
 */

var Foo = new keystone.List('Foo', {
        map: {name: 'fooname'},
        track: true
});

Foo.add({
        bar: { type: Types.Relationship, required: true, initial: true, label: 'Barref', ref: 'Bar', many: false },
        order: { type: Types.Select, required: true, initial: true, label: 'Order', options: _.range(1,100) },
        price: { type: Types.Money, format: '$0,0.00', label: 'Price', required: true, initial: true },
});

Foo.schema.virtual('fooname').get(function() {
        return this.bar+ ' ' + this.order;
});

Foo.defaultColumns = 'fooname, bar, order, price';
Foo.register();

当我使用这个模型定义时,我在 defaultcolumns 列表中看不到虚拟名称。我想创建一个虚拟名称,以便将此模型用作关系时更容易查找。

【问题讨论】:

    标签: keystonejs


    【解决方案1】:

    您不需要虚拟机来执行此操作。 Keystone 允许您在每次保存文档时跟踪和重新计算字段。您可以启用这些选项,以便为您创建一个连接这两个值的函数(同步或异步,您可以选择。)

    我注意到的另一件事是barRelationship,这意味着您需要先填充该关系,然后才能从中获取任何有用的信息。这也意味着您的 value 函数必须是异步的,这就像将回调函数作为参数传递给该函数一样简单。其余的由 Keystone 完成。如果您不需要来自此 bar 的任何信息,而只需要 _id(模型始终具有),则可以不使用我包含的 keystone.list('Bar') 函数。

    http://keystonejs.com/docs/database/#fields-watching

    map 对象还指模型上的一个选项,因此在任何情况下都需要模型上的 fooname 属性,尽管它是动态计算的。

    var keystone = require('keystone'),
        _ = require('underscore');
    var Types = keystone.Field.Types;
    
    /**
     * Foo Model
     * ==================
     */
    
    var Foo = new keystone.List('Foo', {
            map: {name: 'fooname'},
            track: true
    });
    
    Foo.add({
            fooname: { type: Types.Text, watch: true, value: function (cb) {
                // Use this if the "bar" that this document refers to has some information that is relevant to the naming of this document.
                keystone.list('Bar').model.findOne({_id: this.bar.toString()}).exec(function (err, result) {
                    if (!err && result) {
                        // Result now has all the information of the current "bar"
                        // If you just need the _id of the "bar", and don't need any information from it, uncomment the code underneath the closure of the "keystone.list('Bar')" function.
                        return cb(this.bar.name + " " + this.order);
                    }
                });
                // Use this if you don't need anything out of the "bar" that this document refers to, just its _id.
                // return cb(this.bar.toString() + " " + this.order);
            } },
            bar: { type: Types.Relationship, required: true, initial: true, label: 'Barref', ref: 'Bar', many: false },
            order: { type: Types.Select, required: true, initial: true, label: 'Order', options: _.range(1,100) },
            price: { type: Types.Money, format: '$0,0.00', label: 'Price', required: true, initial: true },
    });
    
    Foo.defaultColumns = 'fooname, bar, order, price';
    Foo.register();
    

    【讨论】:

      【解决方案2】:

      试试这个:

      Foo.schema.pre('save', function (next) {
          this.name = this.bar+ ' '+ this.order;
          next();
      });
      

      【讨论】:

      • 虽然这可以解决作者的问题,但纯代码的答案对实际学习帮助不大。您可能会解释为什么这是答案。
      【解决方案3】:

      您能提供更多信息吗?目前在做什么?它应该如何工作? 示例代码?

      编辑:

      创建模型Foo 后,您可以使用属性Foo.schema 访问Mongoose 模式。 (Keystone Concepts)

      这个schema 为所有注册了钩子的方法提供了一个pre-hook。 (Mongoose API Schema#pre)

      其中一种方法是save,可以这样使用:

      Foo.schema.pre('save', function(next){
        console.log('pre-save');
        next();
      });
      

      【讨论】:

      • 编辑了初始帖子以添加模型代码示例和更多解释。谢谢
      猜你喜欢
      • 2019-03-29
      • 2017-06-07
      • 2011-01-11
      • 2019-07-18
      • 2013-12-13
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 2015-04-13
      相关资源
      最近更新 更多