Вопрос

Event input

Доброго дня!

Хочу зробити новий контрол, як в прикладі:

https://academy.terrasoft.ua/docs/developer/139/300/302/kak_dobavlyat_polzovatelskuyu_logiku_v_suschestvuyuschie_elementy_upravleniya

На контрол хочу додати кастомну логіку:

  1. Як можна опрацьовувати подію input  на полі (https://www.w3schools.com/jsref/event_oninput.asp)? При введені кожного символу хочу робити моментальну валідацію введеного тексту.
  2. Як в клас контролу додати додаткові надписи поряд з полем, в яких відображати кількість введених символів та введений текст (червоним виділяти не коректні символи). Як в прикладі на скріні. 

  

 

Прикрепленные файлы

Нравится

3 комментария

Степане, зверніть увагу на текстове поле, яке використовується для введення внутрішніх коментарів. Там при введенні «@» і перших літер прізвища показується панель-список зі знайденими користувачами:

Логіка цього поля реалізована в схемі ESNHtmlEditModule, що успадковується від ExtendedHtmlEditModule. Наприклад, при натисканні клавіш-літер спрацьовує:

/**
 * @inheritdoc Terrasoft.ExtendedHtmlEdit#onKeyPress
 * @overridden
 */
onKeyPress: function(e) {
	if (!this.enabled || this.readonly) {
		return;
	}
	var charCode = e.getCharCode();
	this.lastKeySymbol = String.fromCharCode(charCode);
	if (!e.isNavKeyPress()) {
		if (this.isTrackingStartChar(this.lastKeySymbol)) {
			this.stopTracking();
			this.startTracking();
		}
	}
},

А його застосування реалізовано у ESNFeedConfig:

{
	className: "Terrasoft.ESNHtmlEdit",
	keydown: {bindTo: "onKeyDown"},
	value: {bindTo: "commentMessage"},
	placeholder: resources.localizableStrings.WriteComment,
	classes: {
		htmlEditClass: ["inlineTable", "wide", "editedCommentMessage", "placeholderOpacity"]
	},
	focus: {bindTo: "onNewCommentContainerFocus"},
	blur: {bindTo: "onNewCommentContainerBlur"},
	markerValue: "commentToEditESNHtmlEdit",
	height: "47px",
	prepareList: {bindTo: "prepareEntitiesExpandableList"},
	list: {bindTo: "entitiesList"},
	listViewItemRender: {bindTo: "onEntitiesListViewItemRender"},
	autoGrow: true,
	autoGrowMinHeight: 47
},

Функція prepareEntitiesExpandableList із підключенням серверного сервісу ESNFeedModuleService, що повертає за запитом імена, знаходиться у SocialMentionUtilities.

Зверев Александр, дякую, за відповідь. Але поки чекав відповіді, знайшов як можна реалізувати контрол і щоб він спрацьовував на  EVENT INPUT.

В результаті наслідувався від контрола Terrasoft.controls.MemoEdit, в якого вже реалізований метод onInput.

 

Для використання контрола потрібно в картку додати:

            {

                "operation": "insert",

                "name": "STRINGca49c1a2-6ab9-441e-bc09-46de5d822d60",

                "parentName": "Header",

                "propertyName": "items",

                "values": {

                    "itemType": Terrasoft.ViewItemType.COMPONENT,

                    "className": "Terrasoft.UsrSMSMemoEdit",

                    "value": { "bindTo": "UsrSMSTemplate" },

                    "maxLimit": 160,

                    "caption": "Текст SMS",

                    "layout": {

                        "colSpan": 24,

                        "rowSpan": 2,

                        "column": 0,

                        "row": 0,

                    }

                }

            },

 



Підкріпляю реалізацію з коментарями:

 

define("UsrSMSMemoEdit", ["css!UsrSMSMemoEditCSS"], function () {

    Ext.define("Terrasoft.controls.UsrSMSMemoEdit", {

        extend: "Terrasoft.controls.MemoEdit",

        

        alternateClassName: "Terrasoft.UsrSMSMemoEdit",

        

        caption: null,

        

        maxLimit: 1000,

        

        textCount: 0,

 

        

        errorText: "",

        

        errorVisbility: "hidden",

 

        isErrorTextDataset: "0",

        

        //визначення HTML шаблону

        tpl: [

            "<div id=\"{id}-wrap\" data-resize=\"{resize}\" style=\"{wrapStyle}\">",

            "<div  id=\"{id}-error-block\" class=\"{rightPartClass}\" style=\"visibility:{errorVisbility}\">",

            "<div class=\"{titleCounterClass}\">Помилка:</div>",

            "<div class=\"{errorMarcerCopyClass}\"><div id=\"{id}-error-text\" >{errorText}</div></div>",

            "</div>",

            "<div class=\"{leftPartClass}\">",

            "<div id=\"{id}-title\" class=\"{titleCounterClass}\">",

            "{captionCounter} (<span id=\"{id}-title-counter\">{textCount}</span>/{maxLimit})",

            "</div>",

            "<div class=\"{wrapClass}\">",

            "<div id=\"{id}-scroll\" class=\"{scrollClass}\">",

            "<textarea id=\"{id}-virtual\" class=\"{textareaClasses} virtual\" style=\"{inputStyle}\">"

                +"{value}</textarea>",

            "<textarea id=\"{id}-el\" class=\"{textareaClasses}\" data-is-error-text=\"{isErrorTextDataset}\"",

                "style=\"{inputStyle}\" tabindex=\"{tabIndex}\" ",

                "placeholder=\"{placeholder}\" {spellcheck} {disabled} {readonly}>{value}</textarea>",

            "<div id=\"{id}-disabled-el-icon\" class=\"{disabledElIconClass}\"></div>",

            "</div></div>",

            "<span id=\"{id}-validation\" class=\"{validationClass}\" style=\"{validationStyle}\">"

                +"{validationText}</span>",

            "</div>",

            "</div>"

        ],

        

        //після рендеренгу картки, в якій використовується шаблон та вставлення карткою даних в контрол

        //виконувати перевизначення характеристик контрола та виклик методів,

        //які виконують валідацію та заповнюють HTML шаблон

        setValue: function (value) {

            this.callParent(arguments);

            if(value!==null && value!==undefined ) {

                this.updateControl(value);

            }

        },

        

        /**/

        //при винекнення подій  input та blur

        //виконувати перевизначення характеристик контрола та виклик методів,

        //які виконують валідацію та заповнюють HTML шаблон

        onInput: function () {

            this.callParent(arguments);

            this.updateControl();

        },

        

        onBlur: function () {

            this.callParent(arguments);

            this.updateControl();

        },

        /**/        

        // перевизначення даних які будуть використовуватись в HTML шаблоні

        getTplData: function () {

            var tplData = this.callParent(arguments);

            return Ext.apply(tplData, {

                maxLimit: this.maxLimit,

                captionCounter: this.caption,

                textCount: this.textCount,

                errorText: this.errorText,

                errorVisbility: this.errorVisbility,

                isErrorTextDataset: this.isErrorTextDataset,

            });

        },

         //перевизначення css селекторів, які будуть використовуатись в  HTML шаблоні      

        combineClasses: function () {

            var classes = this.callParent(arguments);

            return Ext.apply(classes, {

                titleCounterClass: ["title-counter"],

                leftPartClass: ["left-part"],

                rightPartClass: ["right-part"],

                errorMarcerCopyClass: ["error-marcer-copy"]

            });

        },

        

        //перевизначення селекторів елементів HTML шаблону,

        //в які будуть апдецйтитись дані

        combineSelectors: function () {

            var selectors = this.callParent(arguments);

            return Ext.apply(selectors, {

                titleCounterEl: "#" + this.id + "-title-counter",

                errorTextEl: "#" + this.id + "-error-text",

                errorBlocEl: "#" + this.id + "-error-block",

            });

        },

        

        // Перевизначення характеристик контрола та виклик методів,

        //які виконують валідацію та заповнюють HTML шаблон

        updateControl: function(value) {

            var text = this.getText(value);

            var length = text.length;

            this.textCount = length;

            var err = this.getSMSTextError(text, this.maxLimit);

            var errorVisbility = err==="" ? "hidden" : "visible";

            this.errorText=err;

            this.errorVisbility=errorVisbility;

            this.isErrorTextDataset = (err === undefined || err === "") ? "0" : "1";

            this.setDataInControlEl();

            this.makeValidationEl(err);

        },

 

        // додавання даних в HTML шаблон 

        setDataInControlEl: function () {

            if(!this.errorBlocEl){return;}

            this.errorBlocEl.dom.style.visibility = this.errorVisbility;

            this.titleCounterEl.update(this.textCount.toString());

            var textarea = this.getEl().dom;

            if (this.errorText || this.errorText === "") {

                this.errorTextEl.dom.innerHTML = this.errorText;

            }

            textarea.dataset.isErrorText = this.isErrorTextDataset;

        },

        

        // отримання ввеленого тексту

        getText: function(value) {

            if(value!==null && value!==undefined ){

                return value;

            }

            var textarea = this.getEl();

            var v = textarea.dom.value;

            var tv = this.getTypedValue();

            var result = v.length > tv.length ? v : tv;

            return result;

        },

        

        // валідація

        makeValidationEl: function (err) {

            var msg = err!=="" ? "Не коректний текст SMS" : "";

            this.validationInfo.invalidMessage =msg;

            this.validationInfo.isValid = err!=="" ? false : true;

            this.setMarkOut();

        },

        

        getSMSTextError: function (str, countLimit) {

            // форматування str додавання тегів в строку

            //....

            return result;

        }

    });

});

Додатково стилізував контрол 

 

div.title-counter {

    font-size: 1.5em;

    color: #4e7bd8;

    height: 2em;

    padding-top: 0.1em;

}

div.left-part{

    width:50%;

    float: left;

}

div.right-part{

    width:50%;

    float: right;

}

.error-marcer-copy {

    border:inherit;

    position: relative;

    display: inline-block;

    clear: both;

    padding-right: 20px;

       padding-left: 20px;

    width: 100%;

    border: inherit;

    vertical-align: top;

    min-height: 28px;

    box-sizing: border-box;

}

.error-marcer-copy > div {

       width: 100%;

    display: inline-block;

    outline: none;

    border: 0px;

    font-size: 1.4em;

    padding: 0;

    box-sizing: border-box;

    height: 100%;

    overflow-y: hidden;

    overflow-wrap: break-word;

}

.right-part > div.title-counter{

    padding-left: 20px;

}

.error-marcer-copy > div > span{

    background-color: red;

}

Показать все комментарии