123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146 |
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- /**
- * @api
- */
- define([
- 'ko',
- 'mageUtils',
- 'underscore',
- 'uiLayout',
- 'uiCollection',
- 'uiRegistry',
- 'mage/translate'
- ], function (ko, utils, _, layout, uiCollection, registry, $t) {
- 'use strict';
- /**
- * Checks value type and cast to boolean if needed
- *
- * @param {*} value
- *
- * @returns {Boolean|*} casted or origin value
- */
- function castValue(value) {
- if (_.isUndefined(value) || value === '' || _.isNull(value)) {
- return false;
- }
- return value;
- }
- /**
- * Compares arrays.
- *
- * @param {Array} base - array as method bases its decision on first argument.
- * @param {Array} current - second array
- *
- * @returns {Boolean} result - is current array equal to base array
- */
- function compareArrays(base, current) {
- var index = 0,
- length = base.length;
- if (base.length !== current.length) {
- return false;
- }
- /*eslint-disable max-depth, eqeqeq, no-use-before-define */
- for (index; index < length; index++) {
- if (_.isArray(base[index]) && _.isArray(current[index])) {
- if (!compareArrays(base[index], current[index])) {
- return false;
- }
- } else if (typeof base[index] === 'object' && typeof current[index] === 'object') {
- if (!compareObjects(base[index], current[index])) {
- return false;
- }
- } else if (castValue(base[index]) != castValue(current[index])) {
- return false;
- }
- }/*eslint-enable max-depth, eqeqeq, no-use-before-define */
- return true;
- }
- /**
- * Compares objects. Compares only properties from origin object,
- * if current object has more properties - they are not considered
- *
- * @param {Object} base - first object
- * @param {Object} current - second object
- *
- * @returns {Boolean} result - is current object equal to base object
- */
- function compareObjects(base, current) {
- var prop;
- /*eslint-disable max-depth, eqeqeq*/
- for (prop in base) {
- if (_.isArray(base[prop]) && _.isArray(current[prop])) {
- if (!compareArrays(base[prop], current[prop])) {
- return false;
- }
- } else if (typeof base[prop] === 'object' && typeof current[prop] === 'object') {
- if (!compareObjects(base[prop], current[prop])) {
- return false;
- }
- } else if (castValue(base[prop]) != castValue(current[prop])) {
- return false;
- }
- }/*eslint-enable max-depth, eqeqeq */
- return true;
- }
- return uiCollection.extend({
- defaults: {
- defaultRecord: false,
- columnsHeader: true,
- columnsHeaderAfterRender: false,
- columnsHeaderClasses: '',
- labels: [],
- recordTemplate: 'record',
- collapsibleHeader: false,
- additionalClasses: {},
- visible: true,
- disabled: false,
- fit: false,
- addButton: true,
- addButtonLabel: $t('Add'),
- recordData: [],
- maxPosition: 0,
- deleteProperty: 'delete',
- identificationProperty: 'record_id',
- deleteValue: true,
- showSpinner: true,
- isDifferedFromDefault: false,
- defaultState: [],
- defaultPagesState: {},
- pagesChanged: {},
- hasInitialPagesState: {},
- changed: false,
- fallbackResetTpl: 'ui/form/element/helper/fallback-reset-link',
- dndConfig: {
- name: '${ $.name }_dnd',
- component: 'Magento_Ui/js/dynamic-rows/dnd',
- template: 'ui/dynamic-rows/cells/dnd',
- recordsProvider: '${ $.name }',
- enabled: true
- },
- templates: {
- record: {
- parent: '${ $.$data.collection.name }',
- name: '${ $.$data.index }',
- dataScope: '${ $.$data.collection.index }.${ $.name }',
- nodeTemplate: '${ $.parent }.${ $.$data.collection.recordTemplate }'
- }
- },
- links: {
- recordData: '${ $.provider }:${ $.dataScope }.${ $.index }'
- },
- listens: {
- visible: 'setVisible',
- disabled: 'setDisabled',
- childTemplate: 'initHeader',
- recordTemplate: 'onUpdateRecordTemplate',
- recordData: 'setDifferedFromDefault parsePagesData setRecordDataToCache',
- currentPage: 'changePage',
- elems: 'checkSpinner',
- changed: 'updateTrigger'
- },
- modules: {
- dnd: '${ $.dndConfig.name }'
- },
- pages: 1,
- pageSize: 20,
- relatedData: [],
- currentPage: 1,
- recordDataCache: [],
- startIndex: 0
- },
- /**
- * Sets record data to cache
- */
- setRecordDataToCache: function (data) {
- this.recordDataCache = data;
- },
- /**
- * Extends instance with default config, calls initialize of parent
- * class, calls initChildren method, set observe variable.
- * Use parent "track" method - wrapper observe array
- *
- * @returns {Object} Chainable.
- */
- initialize: function () {
- _.bindAll(this,
- 'processingDeleteRecord',
- 'onChildrenUpdate',
- 'checkDefaultState',
- 'renderColumnsHeader',
- 'deleteHandler',
- 'setDefaultState'
- );
- this._super()
- .initChildren()
- .initDnd()
- .initDefaultRecord()
- .setInitialProperty()
- .setColumnsHeaderListener()
- .checkSpinner();
- this.on('recordData', this.checkDefaultState);
- return this;
- },
- /**
- * @inheritdoc
- */
- bubble: function (event) {
- if (event === 'deleteRecord' || event === 'update') {
- return false;
- }
- return this._super();
- },
- /**
- * Inits DND module
- *
- * @returns {Object} Chainable.
- */
- initDnd: function () {
- if (this.dndConfig.enabled) {
- layout([this.dndConfig]);
- }
- return this;
- },
- /** @inheritdoc */
- destroy: function () {
- if (this.dnd()) {
- this.dnd().destroy();
- }
- this._super();
- },
- /**
- * Calls 'initObservable' of parent
- *
- * @returns {Object} Chainable.
- */
- initObservable: function () {
- this._super()
- .track('childTemplate')
- .observe([
- 'pages',
- 'currentPage',
- 'recordData',
- 'columnsHeader',
- 'visible',
- 'disabled',
- 'labels',
- 'showSpinner',
- 'isDifferedFromDefault',
- 'changed'
- ]);
- return this;
- },
- /**
- * @inheritdoc
- */
- initElement: function (elem) {
- this._super();
- elem.on({
- 'deleteRecord': this.deleteHandler,
- 'update': this.onChildrenUpdate,
- 'addChild': this.setDefaultState
- });
- return this;
- },
- /**
- * Handler for deleteRecord event
- *
- * @param {Number|String} index - element index
- * @param {Number|String} id
- */
- deleteHandler: function (index, id) {
- var defaultState;
- this.setDefaultState();
- defaultState = this.defaultPagesState[this.currentPage()];
- this.processingDeleteRecord(index, id);
- this.pagesChanged[this.currentPage()] =
- !compareArrays(defaultState, this.arrayFilter(this.getChildItems()));
- this.changed(_.some(this.pagesChanged));
- },
- /**
- * Set initial property to records data
- *
- * @returns {Object} Chainable.
- */
- setInitialProperty: function () {
- if (_.isArray(this.recordData())) {
- this.recordData.each(function (data, index) {
- this.source.set(this.dataScope + '.' + this.index + '.' + index + '.initialize', true);
- }, this);
- }
- return this;
- },
- /**
- * Handler for update event
- *
- * @param {Boolean} state
- */
- onChildrenUpdate: function (state) {
- var changed,
- dataScope,
- changedElemDataScope;
- if (state && !this.hasInitialPagesState[this.currentPage()]) {
- this.setDefaultState();
- changed = this.getChangedElems(this.elems());
- dataScope = this.elems()[0].dataScope.split('.');
- dataScope.splice(dataScope.length - 1, 1);
- changed.forEach(function (elem) {
- changedElemDataScope = elem.dataScope.split('.');
- changedElemDataScope.splice(0, dataScope.length);
- changedElemDataScope[0] =
- (parseInt(changedElemDataScope[0], 10) - this.pageSize * (this.currentPage() - 1)).toString();
- this.setValueByPath(
- this.defaultPagesState[this.currentPage()],
- changedElemDataScope, elem.initialValue
- );
- }, this);
- }
- if (this.defaultPagesState[this.currentPage()]) {
- this.setChangedForCurrentPage();
- }
- },
- /**
- * Set default dynamic-rows state or state before changing data
- *
- * @param {Array} data - defaultState data
- */
- setDefaultState: function (data) {
- var componentData,
- childItems;
- if (!this.hasInitialPagesState[this.currentPage()]) {
- childItems = this.getChildItems();
- componentData = childItems.length ?
- utils.copy(childItems) :
- utils.copy(this.getChildItems(this.recordDataCache));
- componentData.forEach(function (dataObj) {
- if (dataObj.hasOwnProperty('initialize')) {
- delete dataObj.initialize;
- }
- });
- this.hasInitialPagesState[this.currentPage()] = true;
- this.defaultPagesState[this.currentPage()] = data ? data : this.arrayFilter(componentData);
- }
- },
- /**
- * Sets value to object by string path
- *
- * @param {Object} obj
- * @param {Array|String} path
- * @param {*} value
- */
- setValueByPath: function (obj, path, value) {
- var prop;
- if (_.isString(path)) {
- path = path.split('.');
- }
- if (path.length - 1) {
- prop = obj[path[0]];
- path.splice(0, 1);
- this.setValueByPath(prop, path, value);
- } else if (path.length && obj) {
- obj[path[0]] = value;
- }
- },
- /**
- * Returns elements which changed self state
- *
- * @param {Array} array - data array
- * @param {Array} changed - array with changed elements
- * @returns {Array} changed - array with changed elements
- */
- getChangedElems: function (array, changed) {
- changed = changed || [];
- array.forEach(function (elem) {
- if (_.isFunction(elem.elems)) {
- this.getChangedElems(elem.elems(), changed);
- } else if (_.isFunction(elem.hasChanged) && elem.hasChanged()) {
- changed.push(elem);
- }
- }, this);
- return changed;
- },
- /**
- * Checks columnsHeaderAfterRender property,
- * and set listener on elems if needed
- *
- * @returns {Object} Chainable.
- */
- setColumnsHeaderListener: function () {
- if (this.columnsHeaderAfterRender) {
- this.on('recordData', this.renderColumnsHeader);
- if (_.isArray(this.recordData()) && this.recordData().length) {
- this.renderColumnsHeader();
- }
- }
- return this;
- },
- /**
- * Checks whether component's state is default or not
- */
- checkDefaultState: function () {
- var isRecordDataArray = _.isArray(this.recordData()),
- initialize,
- hasNotDefaultRecords = isRecordDataArray ? !!this.recordData().filter(function (data) {
- return !data.initialize;
- }).length : false;
- if (!this.hasInitialPagesState[this.currentPage()] && isRecordDataArray && hasNotDefaultRecords) {
- this.hasInitialPagesState[this.currentPage()] = true;
- this.defaultPagesState[this.currentPage()] = utils.copy(this.getChildItems().filter(function (data) {
- initialize = data.initialize;
- delete data.initialize;
- return initialize;
- }));
- this.setChangedForCurrentPage();
- } else if (this.hasInitialPagesState[this.currentPage()]) {
- this.setChangedForCurrentPage();
- }
- },
- /**
- * Filters out deleted items from array
- *
- * @param {Array} data
- *
- * @returns {Array} filtered array
- */
- arrayFilter: function (data) {
- var prop;
- /*eslint-disable no-loop-func*/
- data.forEach(function (elem) {
- for (prop in elem) {
- if (_.isArray(elem[prop])) {
- elem[prop] = _.filter(elem[prop], function (elemProp) {
- return elemProp[this.deleteProperty] !== this.deleteValue;
- }, this);
- elem[prop].forEach(function (elemProp) {
- if (_.isArray(elemProp)) {
- elem[prop] = this.arrayFilter(elemProp);
- }
- }, this);
- }
- }
- }, this);
- /*eslint-enable no-loop-func*/
- return data;
- },
- /**
- * Triggers update event
- *
- * @param {Boolean} val
- */
- updateTrigger: function (val) {
- this.trigger('update', val);
- },
- /**
- * Returns component state
- */
- hasChanged: function () {
- return this.changed();
- },
- /**
- * Render column header
- */
- renderColumnsHeader: function () {
- this.recordData().length ? this.columnsHeader(true) : this.columnsHeader(false);
- },
- /**
- * Init default record
- *
- * @returns Chainable.
- */
- initDefaultRecord: function () {
- if (this.defaultRecord && !this.recordData().length) {
- this.addChild();
- }
- return this;
- },
- /**
- * Create header template
- *
- * @param {Object} prop - instance obj
- *
- * @returns {Object} Chainable.
- */
- createHeaderTemplate: function (prop) {
- var visible = prop.visible !== false,
- disabled = _.isUndefined(prop.disabled) ? this.disabled() : prop.disabled;
- return {
- visible: ko.observable(visible),
- disabled: ko.observable(disabled)
- };
- },
- /**
- * Init header elements
- */
- initHeader: function () {
- var labels = [],
- data;
- if (!this.labels().length) {
- _.each(this.childTemplate.children, function (cell) {
- data = this.createHeaderTemplate(cell.config);
- cell.config.labelVisible = false;
- _.extend(data, {
- label: cell.config.label,
- name: cell.name,
- required: !!cell.config.validation,
- columnsHeaderClasses: cell.config.columnsHeaderClasses,
- sortOrder: cell.config.sortOrder
- });
- labels.push(data);
- }, this);
- this.labels(_.sortBy(labels, 'sortOrder'));
- }
- },
- /**
- * Set max element position
- *
- * @param {Number} position - element position
- * @param {Object} elem - instance
- */
- setMaxPosition: function (position, elem) {
- if (position || position === 0) {
- this.checkMaxPosition(position);
- this.sort(position, elem);
- } else {
- this.maxPosition += 1;
- }
- },
- /**
- * Sort element by position
- *
- * @param {Number} position - element position
- * @param {Object} elem - instance
- */
- sort: function (position, elem) {
- var that = this,
- sorted,
- updatedCollection;
- if (this.elems().filter(function (el) {
- return el.position || el.position === 0;
- }).length !== this.getChildItems().length) {
- return false;
- }
- if (!elem.containers.length) {
- registry.get(elem.name, function () {
- that.sort(position, elem);
- });
- return false;
- }
- sorted = this.elems().sort(function (propOne, propTwo) {
- return ~~propOne.position - ~~propTwo.position;
- });
- updatedCollection = this.updatePosition(sorted, position, elem.name);
- this.elems(updatedCollection);
- },
- /**
- * Checking loader visibility
- *
- * @param {Array} elems
- */
- checkSpinner: function (elems) {
- this.showSpinner(!(!this.recordData().length || elems && elems.length === this.getChildItems().length));
- },
- /**
- * Filtering data and calculates the quantity of pages
- *
- * @param {Array} data
- */
- parsePagesData: function (data) {
- var pages;
- this.relatedData = this.deleteProperty ?
- _.filter(data, function (elem) {
- return elem && elem[this.deleteProperty] !== this.deleteValue;
- }, this) : data;
- pages = Math.ceil(this.relatedData.length / this.pageSize) || 1;
- this.pages(pages);
- },
- /**
- * Reinit record data in order to remove deleted values
- *
- * @return void
- */
- reinitRecordData: function () {
- this.recordData(
- _.filter(this.recordData(), function (elem) {
- return elem && elem[this.deleteProperty] !== this.deleteValue;
- }, this)
- );
- },
- /**
- * Get items to rendering on current page
- *
- * @returns {Array} data
- */
- getChildItems: function (data, page) {
- var dataRecord = data || this.relatedData,
- startIndex;
- this.startIndex = (~~this.currentPage() - 1) * this.pageSize;
- startIndex = page || this.startIndex;
- return dataRecord.slice(startIndex, this.startIndex + this.pageSize);
- },
- /**
- * Get record count with filtered delete property.
- *
- * @returns {Number} count
- */
- getRecordCount: function () {
- return _.filter(this.recordData(), function (record) {
- return record && record[this.deleteProperty] !== this.deleteValue;
- }, this).length;
- },
- /**
- * Get number of columns
- *
- * @returns {Number} columns
- */
- getColumnsCount: function () {
- return this.labels().length + (this.dndConfig.enabled ? 1 : 0);
- },
- /**
- * Processing pages before addChild
- *
- * @param {Object} ctx - element context
- * @param {Number|String} index - element index
- * @param {Number|String} prop - additional property to element
- */
- processingAddChild: function (ctx, index, prop) {
- this.bubble('addChild', false);
- if (this.relatedData.length && this.relatedData.length % this.pageSize === 0) {
- this.pages(this.pages() + 1);
- this.nextPage();
- } else if (~~this.currentPage() !== this.pages()) {
- this.currentPage(this.pages());
- }
- this.addChild(ctx, index, prop);
- },
- /**
- * Processing pages before deleteRecord
- *
- * @param {Number|String} index - element index
- * @param {Number|String} recordId
- */
- processingDeleteRecord: function (index, recordId) {
- this.deleteRecord(index, recordId);
- },
- /**
- * Change page
- *
- * @param {Number} page - current page
- */
- changePage: function (page) {
- this.clear();
- if (page === 1 && !this.recordData().length) {
- return false;
- }
- if (~~page > this.pages()) {
- this.currentPage(this.pages());
- return false;
- } else if (~~page < 1) {
- this.currentPage(1);
- return false;
- }
- this.initChildren();
- return true;
- },
- /**
- * Check page
- *
- * @returns {Boolean} is page first or not
- */
- isFirst: function () {
- return this.currentPage() === 1;
- },
- /**
- * Check page
- *
- * @returns {Boolean} is page last or not
- */
- isLast: function () {
- return this.currentPage() === this.pages();
- },
- /**
- * Change page to next
- */
- nextPage: function () {
- this.currentPage(this.currentPage() + 1);
- },
- /**
- * Change page to previous
- */
- previousPage: function () {
- this.currentPage(this.currentPage() - 1);
- },
- /**
- * Check dependency and set position to elements
- *
- * @param {Array} collection - elems
- * @param {Number} position - current position
- * @param {String} elemName - element name
- *
- * @returns {Array} collection
- */
- updatePosition: function (collection, position, elemName) {
- var curPos,
- parsePosition = ~~position,
- result = _.filter(collection, function (record) {
- return ~~record.position === parsePosition;
- });
- if (result[1]) {
- curPos = parsePosition + 1;
- result[0].name === elemName ? result[1].position = curPos : result[0].position = curPos;
- this.updatePosition(collection, curPos);
- }
- return collection;
- },
- /**
- * Check max elements position and set if max
- *
- * @param {Number} position - current position
- */
- checkMaxPosition: function (position) {
- var max = 0,
- pos;
- this.elems.each(function (record) {
- pos = ~~record.position;
- pos > max ? max = pos : false;
- });
- max < position ? max = position : false;
- this.maxPosition = max;
- },
- /**
- * Remove and set new max position
- */
- removeMaxPosition: function () {
- this.maxPosition = 0;
- this.elems.each(function (record) {
- this.maxPosition < record.position ? this.maxPosition = ~~record.position : false;
- }, this);
- },
- /**
- * Update record template and rerender elems
- *
- * @param {String} recordName - record name
- */
- onUpdateRecordTemplate: function (recordName) {
- if (recordName) {
- this.recordTemplate = recordName;
- this.reload();
- }
- },
- /**
- * Delete record
- *
- * @param {Number} index - row index
- *
- */
- deleteRecord: function (index, recordId) {
- var recordInstance,
- lastRecord,
- recordsData,
- lastRecordIndex;
- if (this.deleteProperty) {
- recordsData = this.recordData();
- recordInstance = _.find(this.elems(), function (elem) {
- return elem.index === index;
- });
- recordInstance.destroy();
- this.elems([]);
- this._updateCollection();
- this.removeMaxPosition();
- recordsData[recordInstance.index][this.deleteProperty] = this.deleteValue;
- this.recordData(recordsData);
- this.reinitRecordData();
- this.reload();
- } else {
- this.update = true;
- if (~~this.currentPage() === this.pages()) {
- lastRecordIndex = this.startIndex + this.getChildItems().length - 1;
- lastRecord =
- _.findWhere(this.elems(), {
- index: lastRecordIndex
- }) ||
- _.findWhere(this.elems(), {
- index: lastRecordIndex.toString()
- });
- lastRecord.destroy();
- }
- this.removeMaxPosition();
- recordsData = this._getDataByProp(recordId);
- this._updateData(recordsData);
- this.update = false;
- }
- this._reducePages();
- this._sort();
- },
- /**
- * Reduce the number of pages
- *
- * @private
- * @return void
- */
- _reducePages: function () {
- if (this.pages() < ~~this.currentPage()) {
- this.currentPage(this.pages());
- }
- },
- /**
- * Get data object by some property
- *
- * @param {Number} id - element id
- * @param {String} prop - property
- */
- _getDataByProp: function (id, prop) {
- prop = prop || this.identificationProperty;
- return _.reject(this.getChildItems(), function (recordData) {
- return recordData[prop].toString() === id.toString();
- }, this);
- },
- /**
- * Sort elems by position property
- */
- _sort: function () {
- this.elems(this.elems().sort(function (propOne, propTwo) {
- return ~~propOne.position - ~~propTwo.position;
- }));
- },
- /**
- * Set new data to dataSource,
- * delete element
- *
- * @param {Array} data - record data
- */
- _updateData: function (data) {
- var elems = _.clone(this.elems()),
- path,
- dataArr;
- dataArr = this.recordData.splice(this.startIndex, this.recordData().length - this.startIndex);
- dataArr.splice(0, this.pageSize);
- elems = _.sortBy(this.elems(), function (elem) {
- return ~~elem.index;
- });
- data.concat(dataArr).forEach(function (rec, idx) {
- if (elems[idx]) {
- elems[idx].recordId = rec[this.identificationProperty];
- }
- if (!rec.position) {
- rec.position = this.maxPosition;
- this.setMaxPosition();
- }
- path = this.dataScope + '.' + this.index + '.' + (this.startIndex + idx);
- this.source.set(path, rec);
- }, this);
- this.elems(elems);
- },
- /**
- * Rerender dynamic-rows elems
- */
- reload: function () {
- this.clear();
- this.initChildren(false, true);
- },
- /**
- * Destroy all dynamic-rows elems
- *
- * @returns {Object} Chainable.
- */
- clear: function () {
- this.destroyChildren();
- return this;
- },
- /**
- * Reset data to initial value.
- * Call method reset on child elements.
- */
- reset: function () {
- var elems = this.elems();
- _.each(elems, function (elem) {
- if (_.isFunction(elem.reset)) {
- elem.reset();
- }
- });
- },
- /**
- * Set classes
- *
- * @param {Object} data
- *
- * @returns {Object} Classes
- */
- setClasses: function (data) {
- var additional;
- if (_.isString(data.additionalClasses)) {
- additional = data.additionalClasses.split(' ');
- data.additionalClasses = {};
- additional.forEach(function (name) {
- data.additionalClasses[name] = true;
- });
- }
- if (!data.additionalClasses) {
- data.additionalClasses = {};
- }
- _.extend(data.additionalClasses, {
- '_fit': data.fit,
- '_required': data.required,
- '_error': data.error,
- '_empty': !this.elems().length,
- '_no-header': this.columnsHeaderAfterRender || this.collapsibleHeader
- });
- return data.additionalClasses;
- },
- /**
- * Initialize children
- *
- * @returns {Object} Chainable.
- */
- initChildren: function () {
- this.showSpinner(true);
- this.getChildItems().forEach(function (data, index) {
- this.addChild(data, this.startIndex + index);
- }, this);
- return this;
- },
- /**
- * Set visibility to dynamic-rows child
- *
- * @param {Boolean} state
- */
- setVisible: function (state) {
- this.elems.each(function (record) {
- record.setVisible(state);
- }, this);
- },
- /**
- * Set disabled property to dynamic-rows child
- *
- * @param {Boolean} state
- */
- setDisabled: function (state) {
- this.elems.each(function (record) {
- record.setDisabled(state);
- }, this);
- },
- /**
- * Set visibility to column
- *
- * @param {Number} index - column index
- * @param {Boolean} state
- */
- setVisibilityColumn: function (index, state) {
- this.elems.each(function (record) {
- record.setVisibilityColumn(index, state);
- }, this);
- },
- /**
- * Set disabled property to column
- *
- * @param {Number} index - column index
- * @param {Boolean} state
- */
- setDisabledColumn: function (index, state) {
- this.elems.each(function (record) {
- record.setDisabledColumn(index, state);
- }, this);
- },
- /**
- * Add child components
- *
- * @param {Object} data - component data
- * @param {Number} index - record(row) index
- * @param {Number|String} prop - custom identify property
- *
- * @returns {Object} Chainable.
- */
- addChild: function (data, index, prop) {
- var template = this.templates.record,
- child;
- index = index || _.isNumber(index) ? index : this.recordData().length;
- prop = prop || _.isNumber(prop) ? prop : index;
- _.extend(this.templates.record, {
- recordId: prop
- });
- child = utils.template(template, {
- collection: this,
- index: index
- });
- layout([child]);
- return this;
- },
- /**
- * Restore value to default
- */
- restoreToDefault: function () {
- this.recordData(utils.copy(this.default));
- this.reload();
- },
- /**
- * Update whether value differs from default value
- */
- setDifferedFromDefault: function () {
- var recordData = utils.copy(this.recordData());
- Array.isArray(recordData) && recordData.forEach(function (item) {
- delete item['record_id'];
- });
- this.isDifferedFromDefault(!_.isEqual(recordData, this.default));
- },
- /**
- * Set the changed property if the current page is different
- * than the default state
- *
- * @return void
- */
- setChangedForCurrentPage: function () {
- this.pagesChanged[this.currentPage()] =
- !compareArrays(this.defaultPagesState[this.currentPage()], this.arrayFilter(this.getChildItems()));
- this.changed(_.some(this.pagesChanged));
- }
- });
- });
|