All files / util/field/base FieldIteratorMap.js

55.56% Statements 10/18
77.78% Branches 14/18
66.67% Functions 2/3
58.82% Lines 10/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77                                                                    21x     21x 11x       21x 7x       21x 7x 7x   21x 23x                                                
import DefineMap from 'can-define/map/map';
import parseFieldArray from '../parseFieldArray/parseFieldArray';
import mapToFields from '../mapToFields/mapToFields';
import Field from '../Field';
import DefineList from 'can-define/list/list';
 
/**
 * A base class for widgets that need to iterate through a set or subset
 * of fields.
 * ViewModels inheriting this map should define a excludeFieldKey which
 * is a field property that will exclude those fields from this class. For
 * instance, if we are designing an edit widget, an appropriate way to exclude
 * fields from the widget would be to use the key `edit: false` and set
 * `excludeFieldKey: 'edit'` in this class.
 * @class FieldIteratorMap
 */
export default DefineMap.extend({
    /** @lends FieldIteratorMap.prototype */
    /**
   * A string referencing a field property that will exclude that field
   * from this classes fields.
   * @type {String}
   * @memberof FieldIteratorMap.prototype
   */
    excludeFieldKey: 'string',
    /**
   * A getter for an array of fields
   * @type {Array<Field>}
   * @memberof FieldIteratorMap.prototype
   */
    fields: {
        Default: DefineList,
        Type: DefineList,
        get (fields) {
            fields = fields || [];
 
            // if user provides fields, use those
            if (fields.length && !(fields[0] instanceof Field)) {
                fields = parseFieldArray(fields);
            }
            
            // otherwise try to get 'defined' fields from define map properties
            if (!fields.length && this.object instanceof DefineMap) {
                fields = mapToFields(this.object);
            }
 
            // if this fails, serialize the object and use keys of object
            if (!fields.length && this.object) {
                const obj = this.object.get ? this.object.get() : this.object;
                fields = parseFieldArray(Object.keys(obj));
            }
            return fields.filter((f) => {
                return f[this.excludeFieldKey] !== false;
            });
        }
    },
    /**
     * This object's fields mapped to key:value pairs. The key will be 
     * set to the field name, and the object will be the field.
     * @type {Object}
     */
    fieldsMap: {
        get () {
            const fields = this.fields;
            if (!fields) {
                return {};
            }
            const map = {};
            for (let i = 0; i < fields.length; i ++) {
                map[fields[i].name] = fields[i];
            }
 
            return map;
        }
    }
});