UNPKG

fonteva-design-guide

Version:

## Dev, Build and Test

425 lines (393 loc) 13.9 kB
import { LightningElement, api, track } from 'lwc'; import Is_Required from '@salesforce/label/c.Pfm_Is_Required'; import { fireEvent, parseToObject } from 'c/utils'; import getFieldType from '@salesforce/apex/Framework.InputFieldController.getFieldType'; import { registerListener, unregisterAllListeners } from 'c/pubsub'; import { loadScript, loadStyle } from 'lightning/platformResourceLoader'; import BASE from '@salesforce/resourceUrl/PFM_Base'; import lookup from './lookup.html'; import pfmInput from './pfmInput.html'; import validateWcag from 'c/wcag'; // WCAG // Labels are required on all inputs, either in the <legend> of a <fieldset>, or for the <label> related to a field. export default class PfmInput extends LightningElement { @api // text, checkbox, radio, picklist, multipicklist, date, time, lookup, number, address set type(value) { this._type = value; this.isLightningInput = false; // setFieldType will set this to true when type is blank this.setFieldType(); } get type() { return this._type; } _type; @api format; @api label; @api group; @api readOnly = false; @api name; @api tabIndex; @api objectName; @api get disable() { return this.disable; } set disable(value) { this.disabled = value; } // QA_name is the main name of the input field assigned by the system @api get QA_name() { return this.dataName; } set QA_name(value) { this.dataName = value; } // extensions of the QA_name value to include the type of visual that is on the page // e.g. someName-label or someName-input @api QA_name_Label; @api QA_name_Input; @api QA_label; @api fieldId; @api field; @api isValid; @api required = false; @api helpText; @api otherAttributes = {}; @api labels; @api backend; @api customErrorMessage; @api min; @api max; @api step = 1; @api variant = 'standard'; @api align; @api labelHidden; // date attributes: need to clean @api delimiter; @api locale; @api minYear; @api maxYear; @api maxReset; // if set and this.val > this.maxReset then force value to this.maxReset @api minReset; // if set and this.val < this.minReset then force value to this.minReset /** * @deprecated * Should be @track, but we can't remove @api currently; stupid SFDC */ @api get localValue() { return this._localValue; } @track _localValue; @api get options() { return this.localOptions; } set options(val) { this.localOptions = val; } localOptions = []; @track isLightningInput = false; @track isRichText = false; @track isPicklist = false; @track isRadio = false; @track isCheckbox = false; @track isMultiPicklist = false; @track isTextArea = false; @track isFileUpload = false; @track isLookup = false; @track isAddress = false; @track isDate = false; @track errorMessage; @track disabled = false; overrideValidation = false; get hasLabel() { if (this.label == null || this.label === '') { return false; } return true; } _val; @api set val(value) { this._val = value; if (value) { this.updateValue(value[this.name], true); } } get val() { return this._val; } @api toggleFieldStatus(readOnly) { this.disabled = readOnly; } handleDateChange(evt) { this._localValue = evt.detail; fireEvent( this, 'valuechange', { field: this.name, value: this._localValue, group: this.group }, { bubbles: true, composed: true } ); } connectedCallback() { this.QA_name_Input = this.QA_name + '-input'; this.QA_name_Label = this.QA_name + '-label'; this.QA_label = this.QA_label || this.label; this.setAttribute('aria-live', 'polite'); this.loadDependentStyles(); if (!this.backend) { this.classList.add('pfm-input_portal'); } this.errorMessage = Is_Required.replace('{0}', this.label); registerListener('RefreshInputField', this.handleRefreshInputField, this); // known issue, raises `[LWC warning]: If property _localValue decorated with @api` this._localValue = this._val ? this._val[this.name] : undefined; if (this.type == null && this.objectName != null && this.field != null) { getFieldType({ sObjectName: this.objectName, fieldName: this.field }) .then(resultObj => { if (resultObj.isAccessible) { this.type = resultObj.fieldType; this.format = resultObj.format; let localLabel = resultObj.label; if (this.objectName.toLowerCase() === 'contact') { localLabel = localLabel.replace(' Code', ''); } this.label = localLabel; this.helpText = resultObj.helpText; if (!this.required) { this.required = resultObj.isRequired; } if ( !this.otherAttributes || (this.otherAttributes && !this.otherAttributes.parentControllingFieldKey) ) { this.localOptions = resultObj.picklistOptions; } this.disable = !resultObj.isUpdateable; if (!resultObj.isUpdateable) { this.overrideValidation = true; } // known issue, raises `[LWC warning]: If property _localValue decorated with @api` // this._localValue = this.val[this.name]; if (resultObj.defaultValue != null && this._localValue == null) { this._localValue = resultObj.defaultValue; } this.setFieldType(); } }) .catch(error => { console.error( 'Error received: code ' + error.errorCode + ', ' + (error.body ? 'message ' + error.body.message : '') ); }); } else { this.localOptions = this.options; this.setFieldType(); } } renderedCallback() { let self = this; const isValid = validateWcag(self, 'input'); console.debug('IS VALID:', self, isValid); if (!this.hasLabel) { // console.error('The label attribute is empty, this is an accessibility violation. Please add a relevant label to this field.', this, this.template.innerHTML); } if (this.backend && self.template.querySelector('c-pfm-text')) { self.template.querySelector('c-pfm-text').classList.add('pfm-text_backend'); } if (this.align) { this.setAttribute('class', 'pfm-input-align_' + this.align); } } disconnectedCallback() { unregisterAllListeners(this); } setFieldType() { if (this.type == null) { this.type = 'text'; } switch (this.type) { case 'richtext': this.isRichText = true; break; case 'picklist': this.isPicklist = true; break; case 'textarea': this.isTextArea = true; break; case 'fileupload': this.isFileUpload = true; break; case 'reference': case 'lookup': this.isLookup = true; break; case 'radiogroup': this.isRadio = true; break; case 'checkbox': this.isCheckbox = true; break; case 'address': this.isAddress = true; break; case 'multipicklist': this.otherAttributes = parseToObject(this.otherAttributes); // this.localOptions = this.otherAttributes.options; this.isMultiPicklist = true; break; case 'date': this.isDate = true; break; default: this.isLightningInput = true; break; } } handleRefreshInputField(evt) { if (this.group === evt.group) { this.updateValue(evt.data[this.name]); } } @api validate() { let input = this.getInput(); if (input) { this.isValid = input.checkValidity(); input.reportValidity(); } return this.isValid; } @api setErrorMessage(message) { if (!this.isRichText && !this.isPicklist) { let input = this.getInput(); this.callInputFunction(input, 'setCustomValidity', message); this.callInputFunction(input, 'reportValidity'); } } @api updateValue(value, noChangeEvent = false) { let input = this.getInput(); if (!input) { return; } this._localValue = value; if (this.isLightningInput && input) { input.value = value; } if (!noChangeEvent) { fireEvent( this, 'valuechange', { field: this.name, value: value }, { bubbles: true, composed: true } ); } if (input) { this.callInputFunction(input, 'updateValue', value, noChangeEvent); this.callInputFunction(input, 'setCustomValidity', ''); } } callInputFunction(input, functionName, param1, param2) { try { if (typeof input[functionName] === 'function') { input[functionName](param1, param2); } } catch (exp) {} } @api setSelectOptions(options, val) { this.getInput().updateOptions(options, val); } @api clearValue() { this._localValue = null; fireEvent( this, 'valuechange', { field: this.name, value: this._localValue }, { bubbles: true, composed: true } ); if (this.isLookup) { this.getInput().removeValue(); } } @api getChildComponents(selector) { return this.template.querySelectorAll(selector); } getInput() { let input; if (this.isLightningInput || this.isCheckbox) { input = this.template.querySelector('lightning-input'); } else if (this.isTextArea) { input = this.template.querySelector('lightning-textarea'); } else if (this.isRichText) { input = this.template.querySelector('lightning-input-rich-text'); } else if (this.isPicklist) { input = this.template.querySelector('c-pfm-input-picklist'); } else if (this.isFileUpload) { input = this.template.querySelector('c-fileinput'); } else if (this.isLookup) { input = this.template.querySelector('c-pfm-input-lookup'); } else if (this.isAddress) { input = this.template.querySelector('c-pfm-input-address'); } else if (this.isDate) { input = this.template.querySelector('c-pfm-input-date'); } return input; } valueChangedEvent(evt) { this.setErrorMessage(''); if (this.type !== 'checkbox') { this._localValue = evt.detail ? evt.detail.value : evt.target.value; } else { this._localValue = this.getInput().checked; } if (this.maxReset && parseFloat(this._localValue) > this.maxReset) { this.updateValue(String(this.maxReset), true); } if (this.minReset && parseFloat(this._localValue) < this.minReset) { let minResetValue = this.minReset === true ? '0' : this.minReset; this.updateValue(String(minResetValue), true); } fireEvent( this, 'valuechange', { field: this.name, value: this._localValue, group: this.group }, { bubbles: true, composed: true } ); } handleBlurEvent(evt) { fireEvent( this, 'blur', { field: this.name, value: this._localValue, group: this.group }, { bubbles: true, composed: true } ); } loadDependentStyles() { if (!window.pfmInputStylesLoaded) { loadStyle(this, BASE + '/css/component/input/lightning-input.css'); window.pfmInputStylesLoaded = true; } } render() { if (this.type != null) { switch (this.type) { case 'lookup': return lookup; default: return pfmInput; } } return pfmInput; } }