Views: 1932
Last Modified: 24.05.2022

Custom property types

System have the following property types: String, Integer, Yes/No, Enumeration, File, Date and Location. However, you can add your own custom property types and individually determine their external appearance. This way, a value (that you have programmed) will be requested from the buyer during order checkout. To do that, you need to execute the following actions:

  • Inherit custom type class:
    class MyType extends \Bitrix\Sale\Internals\Input\Base
    {
    	protected static function getEditHtmlSingle($name, array $input, $value){...} 
    	protected static function getErrorSingle(array $input, $value){...}
    	static function getSettings(array $input, $reload){...}
    }
    
  • Connect property type to the system: type is connected on the event registerInputTypes:
    \Bitrix\Main\EventManager::getInstance()->addEventHandler(
    	'sale',
    	'registerInputTypes',
    	'myFunction'
    );
    
  • Register your own custom property type in the event handler using the method Manager::register, containing your handler class and name of your type:
    public function myFunction(\Bitrix\Main\Event $event)
    {
    	\Bitrix\Sale\Internals\Input\Manager::register(
    		"myType",
    		array(
    			'CLASS' => '\MyNamespace\MyType',
    			'NAME' => 'My type',
    		)	
    	);
    }
    
  • Describe JS class Sometimes when developing a component, its template must be outfitted with JS functionality, events and other features.

    Learn more...
    operate and connect Before writing JS code, there is an issue: where to store it?

    Learn more...
    the property:
    BX.Sale.Input.Manager.MyType = MyType;
    BX.Sale.Input.Utils.extend(MyType, BX.Sale.Input.BaseInput);
    BX.Sale.Input.Manager.register('myType', MyType);
    
    function MyType(name, settings, value, publicO)
    {
        MyType.__super__.constructor.call(this, name, settings, value, publicO);
    }
    
    MyType.prototype.createEditorSingle = function (name, value)
    {
        ...
    };
    
    MyType.prototype.afterEditorSingleInsert = function (item)
    {
        ...
    };
    
    MyType.prototype.setValueSingle = function (item, value)
    {
        ...
    };
    
    MyType.prototype.getValueSingle = function (item)
    {
        ...
    };
    
    MyType.prototype.setDisabledSingle = function (item, disabled)
    {
        ...
    };
    
    MyType.prototype.addEventSingle = function (item, name, action)
    {
        ...
    };
    

Important! myType type name must be unique within the complete system.

Now, an online store manager will be able to create a new order property with property type you created available among standard types.

Attention! You have to individually enable support for newly created custom property in the order checkout component sale.order.ajax.

Example of created String property type

Inherit the class, connect property type to the system and register it:

class StringInput extends \Bitrix\Sale\Internals\Input\Base 
{
	public static function getEditHtmlSingle($name, array $input, $value)
	{
		if ($input['MULTILINE'] == 'Y')
		{
			$attributes = static::extractAttributes($input,
				array('DISABLED'=>'', 'READONLY'=>'', 'AUTOFOCUS'=>'', 'REQUIRED'=>''),
				array('FORM'=>1, 'MAXLENGTH'=>1, 'PLACEHOLDER'=>1, 'DIRNAME'=>1, 'ROWS'=>1, 'COLS'=>1, 'WRAP'=>1));

			return '<textarea name="'.$name.'"'.$attributes.'>'.htmlspecialcharsbx($value).'</textarea>';
		}
		else
		{
			$attributes = static::extractAttributes($input,
				array('DISABLED'=>'', 'READONLY'=>'', 'AUTOFOCUS'=>'', 'REQUIRED'=>'', 'AUTOCOMPLETE'=>'on'),
				array('FORM'=>1, 'MAXLENGTH'=>1, 'PLACEHOLDER'=>1, 'DIRNAME'=>1, 'SIZE'=>1, 'LIST'=>1, 'PATTERN'=>1));

			return '<input type="text" name="'.$name.'" value="'.htmlspecialcharsbx($value).'"'.$attributes.'>';
		}
	}

	/**
	 * @param $name
	 * @param array $input
	 * @param $value
	 * @return string
	 */
	public static function getFilterEditHtml($name, array $input, $value)
	{
		return static::getEditHtmlSingle($name, $input, $value);
	}

	public static function getErrorSingle(array $input, $value)
	{
		$errors = array();

		$value = trim($value);

		if ($input['MINLENGTH'] && strlen($value) < $input['MINLENGTH'])
			$errors['MINLENGTH'] = Loc::getMessage('INPUT_STRING_MINLENGTH_ERROR', array("#NUM#" => $input['MINLENGTH']));

		if ($input['MAXLENGTH'] && strlen($value) > $input['MAXLENGTH'])
			$errors['MAXLENGTH'] = Loc::getMessage('INPUT_STRING_MAXLENGTH_ERROR', array("#NUM#" => $input['MAXLENGTH']));

		if ($input['PATTERN'] && !preg_match($input['PATTERN'], $value))
			$errors['PATTERN'] = Loc::getMessage('INPUT_STRING_PATTERN_ERROR');

		return $errors;
	}

	static function getSettings(array $input, $reload)
	{
		$settings = array(
			'MINLENGTH' => array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_STRING_MINLENGTH'), 'MIN' => 0, 'STEP' => 1),
			'MAXLENGTH' => array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_STRING_MAXLENGTH'), 'MIN' => 0, 'STEP' => 1),
			'PATTERN'   => array('TYPE' => 'STRING', 'LABEL' => Loc::getMessage('INPUT_STRING_PATTERN'  )),
			'MULTILINE' => array('TYPE' => 'Y/N'   , 'LABEL' => Loc::getMessage('INPUT_STRING_MULTILINE'), 'ONCLICK' => $reload),
		);

		if ($input['MULTILINE'] == 'Y')
		{
			$settings['COLS'] = array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_STRING_SIZE'), 'MIN' => 0, 'STEP' => 1);
			$settings['ROWS'] = array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_STRING_ROWS'), 'MIN' => 0, 'STEP' => 1);
		}
		else
		{
			$settings['SIZE'] = array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_STRING_SIZE'), 'MIN' => 0, 'STEP' => 1);
		}

		return $settings;
	}
}

\Bitrix\Sale\Internals\Input\Manager::register('STRING', array(
	'CLASS' => '\StringInput',
	'NAME' => \Bitrix\Main\Localization\Loc::getMessage('INPUT_STRING'),
));

Describe and connect JS class:

BX.Sale.Input.Manager.StringInput = StringInput;
BX.Sale.Input.Utils.extend(StringInput, BX.Sale.Input.BaseInput);
BX.Sale.Input.Manager.register('STRING', StringInput);

function StringInput(name, settings, value, publicO)
{
	StringInput.__super__.constructor.call(this, name, settings, value, publicO);
}

StringInput.prototype.createEditorSingle = function (name, value)
{
	var s, size = 5, settings = this.settings;

	if ((s = settings.MIN) && s.toString().length > size)
		size = s;

	if ((s = settings.MAX) && s.toString().length > size)
		size = s;

	if ((s = settings.STEP) && s.toString().length > size)
		size = s;

	var element = document.createElement('input');
	element.type  = 'text';
	element.name  = name;
	element.value = value;
	element.size  = size;

	BX.Sale.Input.Utils.applyBooleanAttributesTo(element, settings, BX.Sale.Input.Utils.globalBooleanAttributes, {DISABLED:'', READONLY:'', AUTOFOCUS:'', REQUIRED:'', AUTOCOMPLETE:'on'});
	BX.Sale.Input.Utils.applyValueAttributesTo(element, settings, BX.Sale.Input.Utils.globalValueAttributes, {FORM:1, LIST:1, PLACEHOLDER:1});
	this.applyEventAttributesTo(element, settings, BX.Sale.Input.Utils.globalEventAttributes);

	return [element];
};

StringInput.prototype.afterEditorSingleInsert = function (item)
{
	item[0].focus();
};

StringInput.prototype.setValueSingle = function (item, value)
{
	item[0].value = value;
};

StringInput.prototype.getValueSingle = function (item)
{
	var element = item[0];
	return element.disabled ? null : element.value;
};

StringInput.prototype.setDisabledSingle = function (item, disabled)
{
	item[0].disabled = disabled;
};

StringInput.prototype.addEventSingle = function (item, name, action)
{
	BX.Sale.Input.Utils.addEventTo(item[0], name, action);
};



Courses developed by Bitrix24