All files / util/field Field.js

80% Statements 12/15
66.67% Branches 8/12
75% Functions 3/4
80% Lines 12/15

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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193                                    12x                           69x 69x   69x 69x   69x                                         2x 2x                                               12x 11x   12x                                                                                                                                                                                                       12x          
import {makeSentenceCase} from '../string/string';
import DefineMap from 'can-define/map/map';
import DefineList from 'can-define/list/list';
import {getEditComponent} from './fieldComponents';
 
/**
 * @typedef ValidationObject
 * @name ValidationObject
 * @property {Object} object the form object that was set on the form
 * @property {Object} dirty the updated object currently set by the user in the form
 * @property {*} value the current field's value (dirty). Same as `dirty[field.name]` but provided for easy access
 */
 
/**
 * @class Field
 * @description Constructs a new field. Used throughout spectre-canjs to 
 * define displays of properties, aka fields. 
 */
export const Field = DefineMap.extend('Field', {
 
    // allow extra properties on this type
    seal: false
}, {
    /** @lends Field.prototype */
    /**
     * The name of the type on the object, this field's name
     * @type {String} 
     * @memberof Field.prototype
     */
    name: {
        type: 'string',
        set (name) {
            Eif (!this.alias && name) {
                this.alias = makeSentenceCase(name);
            }
            Eif (!this.classes && name) {
                this.classes = 'cell-' + name;
            }
            return name;
        }
    },
    /**
     * A friendly name for the field used to display to the user
     * The default is to capitalize the name and remove underscores
     * @type {String}
     * @memberof Field.prototype
     */
    alias: {
        type: 'string'
    },
    /**
     * A virtual property that is used as a shorthand for setting all
     * properties on this field. This value doesn't actually get set 
     * and will never return anything.
     * @type {Object}
     * @memberof Field.prototype
     */
    properties: {
        set (props) {
            this.assign(props);
            return;
        }
    },
    /**
     * The field error string
     * @type {String}
     * @memberof Field.prototype
     */
    error: 'string',
    /**
     * The form object. Passed to fields so they can use it in cascading dropdowns...etc 
     * @type {Object}
     * @memberof Field.prototype
     */
    object: DefineMap,
    /**
     * The current field value
     * @type {Object}
     * @memberof Field.prototype
     */
    value: {
        default: '',
        type: '*',
        set (val) {
            if (this.value !== val) {
                this.dispatch('fieldchange', [this]);
            }
            return val;
        }
    },
    /**
     * Includes this field in the list view in the data-admin
     * @type {Boolean} Field.prototype.list list
     * @memberof Field.prototype
     */
    list: {
        type: 'boolean',
        default: true
    },
    /**
     * Includes this field in the details view in the data-admin
     * @type {Boolean} Field.prototype.detail detail
     * @memberof Field.prototype
     */
    detail: {
        type: 'boolean',
        default: true
    },
    /**
     * Includes this field in the edit view in the data-admin
     * @type {Boolean} Field.prototype.edit edit
     * @memberof Field.prototype
     */
    edit: {
        type: 'boolean',
        default: true
    },
    /**
     * Includes this field in the filter widget's fields.
     * @type {Boolean} Field.prototype.filter filter
     * @memberof Field.prototype
     */
    filter: {
        type: 'boolean',
        default: true
    },
    /**
     * Includes this field in the sorting capability
     * @type {Boolean} Field.prototype.sort sort
     * @memberof Field.prototype
     */
    sort: {
        type: 'boolean',
        default: true
    },
    /**
     * A boolean flag to display form field inline with others and hide labels
     * @type {Boolean} Field.prototype.inline inline
     * @memberof Field.prototype
     */
    inline: 'boolean',
    /**
     * Text to display when the field is empty (like a textbox). Doesn't apply to
     * some fields, like select or date fields.
     * @type {String} Field.prototype.placeholder placeholder
     * @memberof Field.prototype
     */
    placeholder: 'string',
    /**
     * Adds css classes to the table cells and headings. Selectors should use
     * `th.classname` and `td.classname`
     * @type {String} Field.prototype.classes classes
     * @memberof Field.prototype
     */
    classes: 'string',
 
    // placeholder props to overwrite the display template of edit or table components
    editTag: {
        default: 'sp-text-field', 
        type: 'string'
    },
    editComponent: {
        get (comp) {
            
            if (typeof comp === 'function') {
                return comp;
            }
            return getEditComponent(this);
        }
    },
    displayComponent: {},
    /**
     * If field component implements this method, it will be called 
     * when the component is inserted, with the input element
     * It can be used to customize the input, like adding a date picker
     * 
     */
    onInsert: {}, // (element) {flatpicker(element);}
    /**
     * Validates a type and returns a string if the field is invalid
     * @param {ValidationObject} props A special object consisting of information about the current value and dirty state of the form object
     * @return {String|falsey} a string error message if the value is not valid or undefined if there is no error message
     */
    validate: { }
});
 
 
export const FieldList = DefineList.extend('FieldList', {
    '#': Field
});
 
export default Field;