UNPKG

@red-code-mp/mp-builder

Version:

* [Structure](#Structure) * [Route](#Route) * [Endpoints](#Endpoints) * [Table](#Table) * [Lang](#Lang) * [Menu](#Menu) * [Toast](#Toast)

462 lines (448 loc) 14 kB
import Base from './base' export default { name: 'Options-Name', /** * the used mixins * @author Amr */ mixins: [Base], /** * field's component * @author Amr */ props: { field: { required: true, default: () => { return {} } }, }, data() { return { defaultParsable: { id: 'id', label: 'name' }, options$$: [], serviceOptions$$: [], staticOptions$$: [], hasRelationChanged: false, extraParams: {}, relatedField: null }; }, computed: { /** * bind formData's keys with the rowKey * @private * @author Amr */ __rowedKeyData() { let __copyFormData = {} Object.keys(this.clone(this.formData)).map((el) => { let key = this.rowKey ? `${el}--${this.rowKey}` : el; __copyFormData[key] = this.formData[el]; }) return __copyFormData; }, /** * get the passed component * * @return {default.props.component|{require}} * @author Amr */ component$() { return this.clone(this.field); }, /** * check if the select is multiple * @return {*} * @author Amr */ isMultiple() { return this.component$.multiple; }, /** * returns the parsable object * @return {defaultParsable|{id, label}|*} * @private * @author Amr */ __parsable() { let hasParsable = this.component$.hasOwnProperty('parsable') if (hasParsable) return this.component$.parsable return this.defaultParsable; }, /** * component's options * @author Amr */ __options: { get() { return this.parse([].concat(this.__serviceOptions, this.__staticOptions)) }, set(options) { this.options$$ = options; } }, /** * component's options * @author Amr */ __serviceOptions: { get() { return this.serviceOptions$$; }, set(options) { this.serviceOptions$$ = options; } }, /** * component's options * @author Amr */ __staticOptions: { get() { return this.staticOptions$$; }, set(options) { this.staticOptions$$ = options; } }, filter() { let filter = this.component$.filter; if (filter && filter instanceof Function) return filter; throw new Error('Not filter passed') }, __hasRelations() { return this.component$.hasOwnProperty('relations'); }, __relations() { if (!this.__hasRelations) throw new Error('Has no relation'); let relations = []; let isObject = this.isObject(this.component$.relations); if (isObject) { relations.push(this.component$.relations); } else relations = relations.concat(this.component$.relations) return this.__updateRelationsFields(this.clone(relations)); }, /** * @author khalid * bind element attributes */ __attributes() { return this.component$.attributes ?? {} } }, methods: { /** * remove the row key from came string value * @param value * @return {*} * @private * @author Amr */ __removeRowKey(value) { return value.replace(/--(\w)+$/, '') }, /** * update the field of component * if component came from repeater and out_side attribute is true * them attach the rowKey with the name of field * otherwise take the name * @param relations * @return {*} * @private * @author Amr */ __updateRelationsFields(relations) { return this.clone(relations).map((component) => { let __component = this.clone(component); if (!__component.out_side && this.rowKey) { __component.field = this.__removeRowKey(__component.field) __component.field = `${__component.field}--${this.rowKey}` } return __component; }) }, prepareRelationParams(relation, value) { let bindedAttributes = relation.bind; let field = relation.field; field = this.__removeRowKey(field) if (!value) return; let attr = {} if (this.isArray(value)) { attr[`${field}${this.ucfirst(bindedAttributes)}`] = JSON.stringify(value); } else if (typeof value == 'number') { attr[`${field}${this.ucfirst(bindedAttributes)}`] = value } else { bindedAttributes.forEach((key) => { let keyValue = value[key]; if (keyValue) attr[`${field}${this.ucfirst(key)}`] = keyValue }) } return attr; }, __pushRelationChanges(values) { this.extraParams = { ...values } this.__serviceWatcher(this.component$.service) FormRelations.$emit(this.__rowKey, values) }, /** * call the service of component to update * the options of select * @param relation * @param value * @private *@author Amr */ __updateRelationListener(relation, value) { this.hasRelationChanged = true; let queries = this.prepareRelationParams(relation, value) this.__pushRelationChanges(queries) }, __getDataOfRepeater(field) { let __field = this.__removeRowKey(field) if (this.formData && this.formData[__field]) { return this.formData[__field]; } return this.allFormData[field]; }, listenToRelations() { try { let relations = this.__relations; relations.forEach((relation) => { let field = this.clone(relation).field this.relatedField = field if (this.allFormData[field] || this.__rowedKeyData[field]) { this.__updateRelationListener(this.clone(relation), this.__getDataOfRepeater(field)); } else { FormBuilder.$on(field, (value) => { if (!value) return; this.__updateRelationListener(this.clone(relation), value); }) } }) } catch (e) { return; } }, /** * walk through the objects * * @param object * @return {{id: *, label: *}} * @author Amr */ mapParsing(object) { return { id: object[this.__parsable.id], label: object[this.__parsable.label], ...object } }, /** * parse object accordin' to the given * parsable object * * @param options * @return {*} * @author Amr */ parse(options) { return options.map(this.mapParsing) }, /** * prepare request's params * * @param params * @return {{select: boolean}|any} * @private * @author Amr */ __getParams(params = {}) { let $params = { type: 'select', ...this.extraParams } if (params == undefined || params == null) return $params; let _params = this.prepareParams(params) return Object.assign($params, _params) }, /** * returns request's queries * * @param query * @return {*|{}} * @private * @author ¬Amr */ __getQueries(query = {}) { let __query = {} if (!query) return __query; Object.keys(query).forEach(key => { let value = query[key]; if (value instanceof Function) value = value.call(this) this.set(__query, key, value); }) return __query ?? {}; }, /** * prepare the request's instance * @param link * @return {*|Promise<unknown>} * @private * @author Amr */ __optionRequest(link) { return this.request(link); }, /** * prepare request's link * * @param service * @return {*} * @private * @author Amr */ __prepareLink(service) { let params = this.__getParams(service.params) let queries = this.__getQueries(service.query) // console.log('queries', queries, params) return this.route(service.route, queries, params) }, /** * fetch data from the backend * @param service * @return {*|*|Promise<unknown>} * @author Amr */ fetchOptions(service) { let link = this.__prepareLink(service); return this.__optionRequest(link); }, /** * append new options to the options$$ * global var * @param options * @private * @author Amr */ __concatWithNewOptions(options) { try { options = options.filter(this.filter) } catch (e) { } finally { let $options = this.parse(options) this.__options = this.__options.concat($options) } }, /** * track options attribute' changes * @param newVal * @param oldVal * @return {*} * @private * @author Amr */ __optionsWatcher(newVal, oldVal) { this.__fetchOptions(newVal, (payload) => { this.__reAssignModel$(); }) }, __reAssignModel$() { }, __fetchService(newVal, handel = () => { }) { this.fetchOptions(newVal).then((result) => { this.__serviceOptions = result.payload console.log('service-options', this.__serviceOptions) handel(result); }); }, __fetchOptions(options, handler = () => { }) { if (!Array.isArray(options)) return options; this.__staticOptions = options; handler(options); }, /** * watch endpoint changes * @param newVal * @param oldVal * @private * @author Amr */ __serviceWatcher(newVal, oldVal) { if (!newVal) return; if (this.__hasRelations && !this.hasRelationChanged) return; this.__fetchService(newVal, (payload) => { this.__reAssignModel$(); }) }, __hasReAssigned(val) { return parseInt(val, 10) || !this.isArrayOfObject(val); }, /** * publish model's value via FormBuilder Bus * @param newVal * @param oldVal * @author Amr */ model$Watcher(newVal, oldVal) { if (newVal && this.__hasReAssigned(newVal) && this.__options.length) this.__reAssignModel$(); this.publish(this.__model); if (newVal !== oldVal) { let event = { field: this.__field, newValue: newVal, oldValue: oldVal, index: this.indexRow, rowKey: this.rowKey, rootField: this.rootField } this.$parent.$emit('updateValue', event) FormBuilder.$emit('repeater-fields', event) } }, }, watch: { 'component$.service': { deep: true, immediate: true, handler: '__serviceWatcher' }, 'component$.options': { deep: true, immediate: true, handler: '__optionsWatcher' }, __options: { deep: true, immediate: true, handler(options) { FormBuilder.$emit('options-all', this.__rowKey, options) } } }, created() { this.listenToRelations(); }, beforeDestroy() { // FormRelations.$off(this.__rowKey) // FormBuilder.$off(this.relatedField) } }