Jump to content

ProcessModule: API InputField - is it possible to set readonly?


Gadgetto
 Share

Recommended Posts

In a ProcessModule I'm trying to set an API InputFieldSelect or InputFieldText to readyonly using the HTML attr readonly="readonly".

I have tried this but this has no effect:

            /** @var InputfieldSelect $f */
            $f = $modules->get('InputfieldSelect');
            if ($action == 'edit') $f->attr('readonly', 'readonly');
            $f->name = 'type';
            $f->label = $this->_('Type');
            $f->required = true;
            $f->value = $type;
            $f->columnWidth = 100;
            $f->addOptions($this->getDiscountsTypes());

The HTML source looks OK (it has the readonly attr), but the readonly attribute seems to be ignored.

<select id="Inputfield_type" class="required uk-select" name="type" readonly="readonly">
  ...
</select>

Is this possible?

Link to comment
Share on other sites

1 hour ago, Gadgetto said:

<select id="Inputfield_type" class="required uk-select" name="type" readonly="readonly"> ... </select>

HTML specs say select tag does not have readonly attribute. Use disabled instead. I think a disabled select will not POST though.

  • Like 1
Link to comment
Share on other sites

13 minutes ago, kongondo said:

I think a disabled select will not POST though.

Correct, the trick here is to disable all options except the one which need to be submited.

 

<select>
    <option value="1" disabled>one</option>
    <option value="2" disabled>two</option>
    <option value="3" selected>three</option>
</select>

 

Edited by flydev
example
  • Like 1
Link to comment
Share on other sites

35 minutes ago, bernhard said:

Can't you just set the inputfield collapsed to collapsedNoLocked https://processwire.com/api/ref/inputfield/#pwapi-methods-collapsed-constants

Setting to Inputfield::collapsedNoLocked renders the field as simple list item without a form field element. So the locked/readonly value won't be submitted.

Link to comment
Share on other sites

The best way to simulate a readonly InputfieldSelect seems to be:

  1. set an disabled attr to the desired select field "myfield"
  2. change the name of the select field to e.g. "myfield_disabled"
  3. use an additional hidden form field and give it the name of the disabled select field "myfield"

The only problem I have after this is, that the form processing complains that the field has no value - but this should be solvable...

Link to comment
Share on other sites

4 minutes ago, bernhard said:

I think I don't understand what you are trying to do. Why do you need a readonly select? What is the difference to a locked field that just shows the value?

The locked/disabled field value won't be in the post array. The value should be posted but not be editable.

I feed the SnipCart REST API with an array of key->value pairs and the "not editable" value still needs to be in the array.

Link to comment
Share on other sites

4 minutes ago, bernhard said:

OK thx for the clarification ? 

The problem is $form->processInput($input->post) won't populate the disabled field as the value isn't in the post array. And the disabled select field is empty after posting.
So I'm now trying to get the field populated "after" the form is processed or something else - really don't know how to do it currently ...

Link to comment
Share on other sites

It would be great to get a more detailed description of your problem and what you have so far and what you want to do and what and why the current solution is a problem. You can of course hook processInput and you can set any values there as you like. But it's hard to give an advice when you don't have the bigger picture ? 

Link to comment
Share on other sites

Here is the complete method to process the form!

Please note:
This code isn't finished and some parts (e.g. validation and sanitation part) may look unnecessary...

The form can be used for editing (update) or adding (create) SnipCart discounts. In editing mode the method is called with a SnipCart payload ($item) array from REST API and the form is populated with the fetched values. In adding mode the form is populated with default values.

Some fields like the documented field below in code (near the middle of the code), needs to be readonly in edit mode as not all parts of a SnipCart discount can be changed after creation. The problem is, a SELECT field can't be set to "readonly" in HTML - only "disabled" is possible. But a disabled field won't be submitted when form is posted.

For a good user experience I'd like to simulate a readonly field and submit the value of the disabled select field with the help of a hidden field.

This works so far, except that I wasn't able to populate the disabled select field after the form was submitted and the $form->processInput($input->post) method was called.

This is the problem I'd like to solve.

Maybe someone has an idea on how to do this.

Spoiler

    /**
     * Render and process the discount form.
     * (Edit or Add)
     *
     * @param array $item (optional)
     * @param string $ret A return URL (optional)
     * @return markup 
     *
     */
    private function _processDiscountForm($item = null, $ret = '') {
        $modules = $this->wire('modules');
        $sanitizer = $this->wire('sanitizer');
        $input = $this->wire('input');
        $session = $this->wire('session');

        $mode = ($item) ? 'edit' : 'add';

        $expiresDateFormat = 'Y-m-d';
        $expiresPlaceholder = 'YYYY-MM-DD';
        $expiresMinDate = wireDate($expiresDateFormat);
        
        if (!$input->post->saving_discount_active) {

            if ($mode == 'edit') {
                // Get values from payload
                $discount = array(
                    'id' => $item['id'],
                    'name' => $item['name'],
                    'expires' => $item['expires'],
                    'maxNumberOfUsages' => $item['maxNumberOfUsages'],
                    'currency' => (isset($item['currency']) ? $item['currency'] : ''), // currency field isn't always present
                    'combinable' => $item['combinable'],
                    'type' => $item['type'],
                    'type_disabled' => $item['type'], // needed to simulate a readonly select in edit mode
                    'amount' => $item['amount'],
                    'rate' => $item['rate'],
                    'alternatePrice' => $item['alternatePrice'],
                    'shippingDescription' => $item['shippingDescription'],
                    'shippingCost' => $item['shippingCost'],
                    'shippingGuaranteedDaysToDelivery' => $item['shippingGuaranteedDaysToDelivery'],
                    // ... more fields to be added
                    
                    'trigger' => $item['trigger'],
                );
            } else {
                // Set default values (if action = add)
                $discount = array(
                    'id' => '',
                    'name' => '',
                    'expires' => '',
                    'maxNumberOfUsages' => 1,
                    'currency' => '',
                    'combinable' => '1',
                    'type' => 'FixedAmount',
                    'amount' => '',
                    'rate' => '',
                    'alternatePrice' => '',
                    'shippingDescription' => '',
                    'shippingCost' => '',
                    'shippingGuaranteedDaysToDelivery' => '',
                    // ... more fields to be added
                    
                    'trigger' => 'Code',
                );
            }
        }

		/** @var InputfieldForm $form */
        $form = $modules->get('InputfieldForm');
        $form->attr('id', 'DiscountForm');
		$form->attr('action', $this->currentUrl);
        $form->attr('method', 'post');

            if ($ret) {
                /** @var InputfieldHidden $f */
                $f = $modules->get('InputfieldHidden');
                $f->attr('name', 'ret');
                $f->attr('value', urlencode($ret));
    
                $form->add($f);
            }

            /** @var InputfieldHidden $f */
    		$f = $modules->get('InputfieldHidden');
            $f->attr('name', 'saving_discount_active');
            $f->attr('value', true);

        $form->add($f);

            /** @var InputfieldHidden $f */
            $f = $modules->get('InputfieldHidden');
            $f->attr('name', 'id');

        $form->add($f);

            /** @var InputfieldFieldset $fieldset */
            $fieldset = $modules->get('InputfieldFieldset');
            $fieldset->label = $this->_('General Information');
            $fieldset->icon = 'info-circle';

        $form->add($fieldset);

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'name');
            $f->label = $this->_('Discount name');
            $f->required = true;
            $f->columnWidth = 50;

        $fieldset->add($f);
            
            /** @var InputfieldDatetime $f */
            $f = $modules->get('InputfieldDatetime');
            $f->attr('name', 'expires');
            $f->attr('placeholder', $expiresPlaceholder);
            $f->label = $this->_('Expires');
            $f->detail = $this->_('Leave empty to never expire');
            $f->size = 100;
            $f->datepicker = InputfieldDatetime::datepickerFocus;
            $f->dateInputFormat = $expiresDateFormat;
            $f->columnWidth = 50;

        $fieldset->add($f);

            /** @var InputfieldInteger $f */
            $f = $modules->get('InputfieldInteger');
            $f->attr('name', 'maxNumberOfUsages');
            $f->label = $this->_('Maximum number of usages');
            $f->detail = $this->_('Leave empty to enable unlimited usage');
            $f->size = 100;
            $f->min = 1;
            $f->columnWidth = 50;

        $fieldset->add($f);

            /** @var InputfieldSelect $f */
            $f = $modules->get('InputfieldSelect');
            $f->attr('name', 'currency');
            $f->label = $this->_('Currency');
            $f->columnWidth = 50;
            $supportedCurrencies = CurrencyFormat::getSupportedCurrencies();
            foreach ($this->currencies as $currencyOption) {
                $currencyLabel = isset($supportedCurrencies[$currencyOption])
                    ? $supportedCurrencies[$currencyOption]
                    : $currencyOption;
                $f->addOption($currencyOption, $currencyLabel);
            }

        $fieldset->add($f);

            /** @var InputfieldCheckbox $f */
            $f = $modules->get('InputfieldCheckbox');
            $f->attr('name', 'combinable');
            $f->label = $this->_('Combination with other discounts allowed?');

        $fieldset->add($f);

            /** @var InputfieldFieldset $fieldset */
            $fieldset = $modules->get('InputfieldFieldset');
            $fieldset->label = $this->_('Choose Discount Actions');
            $fieldset->icon = 'cogs';
            $fieldset->set('themeOffset', 1);

        $form->add($fieldset);

//
//
//
// The following field (+ the next hidden field) is meant to simulate a readonly InputfieldSelect.
//
// The problem is, the select field needs to be populated with a value even when "disabled"
// which doesn't work out of the box, as $form->processInput($input->post) can't populate it
// because the disabled field isn't submitted.
//
//
//

            /** @var InputfieldSelect $f */
            $f = $modules->get('InputfieldSelect');
            if ($mode == 'edit') {
                // simulate a readonly select in edit mode
                $f->attr('name', 'type_disabled');
                $f->attr('disabled', 'disabled');
            } else {
                $f->attr('name', 'type');
            }
            $f->addClass('InputfieldMaxWidth');
            $f->label = $this->_('Type');
            $f->required = true;
            $f->addOptions($this->getDiscountsTypes());

        $fieldset->add($f);

            if ($mode == 'edit') {
                // needed to simulate a readonly select in edit mode
                /** @var InputfieldHidden $f */
                $f = $modules->get('InputfieldHidden');
                $f->attr('name', 'type');

                $fieldset->add($f);
            }

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'amount');
            $f->attr('pattern', '[-+]?[0-9]*[.]?[0-9]+');
            $f->label = $this->_('Amount');
            $f->detail = $this->_('Decimal with a dot (.) as separator e.g. 19.99');
            $f->required = true;
            $f->showIf = 'type=FixedAmount|FixedAmountOnItems|FixedAmountOnCategory|AmountOnSubscription';
            $f->requiredIf = 'type=FixedAmount|FixedAmountOnItems|FixedAmountOnCategory|AmountOnSubscription';

        $fieldset->add($f);

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'rate');
            $f->attr('pattern', '[-+]?[0-9]*[.]?[0-9]+');
            $f->label = $this->_('Rate in %');
            $f->detail = $this->_('Decimal with a dot (.) as separator e.g. 2.5');
            $f->required = true;
            $f->showIf = 'type=Rate|RateOnItems|RateOnCategory|RateOnSubscription';
            $f->requiredIf = 'type=Rate|RateOnItems|RateOnCategory|RateOnSubscription';

        $fieldset->add($f);

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'alternatePrice');
            $f->label = $this->_('Alternate price list');
            $f->detail = $this->_('The name of the alternate price list to use');
            $f->required = true;
            $f->showIf = 'type=AlternatePrice';
            $f->requiredIf = 'type=AlternatePrice';

        $fieldset->add($f);

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'shippingDescription');
            $f->label = $this->_('Shipping description');
            $f->detail = $this->_('The shipping method name that will be displayed to your customers');
            $f->required = true;
            $f->showIf = 'type=Shipping';
            $f->requiredIf = 'type=Shipping';

        $fieldset->add($f);

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'shippingCost');
            $f->attr('pattern', '[-+]?[0-9]*[.]?[0-9]+');
            $f->label = $this->_('Shipping amount');
            $f->detail = $this->_('Decimal with a dot (.) as separator e.g. 4.5');
            $f->required = true;
            $f->showIf = 'type=Shipping';
            $f->requiredIf = 'type=Shipping';
            $f->columnWidth = 50;

        $fieldset->add($f);

            /** @var InputfieldInteger $f */
            $f = $modules->get('InputfieldInteger');
            $f->attr('name', 'shippingGuaranteedDaysToDelivery');
            $f->label = $this->_('Guaranteed days to delivery');
            $f->detail = $this->_('The number of days it will take for shipping (can be empty)');
            $f->size = 100;
            $f->min = 1;
            $f->showIf = 'type=Shipping';
            $f->columnWidth = 50;

        $fieldset->add($f);

            // more fields to be added ...



            /** @var InputfieldFieldset $fieldset */
            $fieldset = $modules->get('InputfieldFieldset');
            $fieldset->label = $this->_('Choose Discount Conditions');
            $fieldset->icon = 'scissors';

        $form->add($fieldset);

            /** @var InputfieldSelect $f */
            $f = $modules->get('InputfieldSelect');
            $f->attr('name', 'trigger');
            $f->addClass('InputfieldMaxWidth');
            $f->label = $this->_('Trigger');
            $f->required = true;
            $f->addOptions($this->getDiscountsTriggers());

        $fieldset->add($f);

            // more fields to be added ...



            /** @var InputfieldSubmit $btn */
            $btn = $modules->get('InputfieldSubmit');
            $btn->attr('id', 'SaveDiscountButton');
            $btn->attr('name', 'save_discount');
            $btn->attr('value', $this->_('Save discount'));

        $form->add($btn);

        // Render form without processing if not submitted
        if (!$input->post->saving_discount_active) {
            $form->populateValues($discount);
            return $form->render();
        }
        
        $form->processInput($input->post);

        // Get values and validate input
        $name = $form->get('name');
        $nameValue = $name->value;

        $expires = $form->get('expires');
        $expiresValue = $expires->value;
        if ($mode == 'add' && $expiresValue && !$sanitizer->date($expiresValue, $expiresDateFormat, array('min' => $expiresMinDate))) {
            $expires->error(sprintf($this->_('Minimum allowed date is %s (today)'), $expiresMinDate));
        }

        $maxNumberOfUsages = $form->get('maxNumberOfUsages');
        $maxNumberOfUsagesValue = $maxNumberOfUsages->value;

        $currency = $form->get('currency');
        $currencyValue = $currency->value;

        $combinable = $form->get('combinable');
        $combinableValue = $combinable->value;

        $type = $form->get('type');
        $typeValue = $type->value;

        $amount = $form->get('amount');
        $amountValue = $amount->value;
        if ($amountValue && !checkPattern($amountValue, '^[-+]?[0-9]*[.]?[0-9]+$')) {
            $amount->error($this->_('Wrong format! Please use decimal with a dot (.) as separator e.g. 19.99'));
        }

        $rate = $form->get('rate');
        $rateValue = $rate->value;
        if ($rateValue && !checkPattern($rateValue, '^[-+]?[0-9]*[.]?[0-9]+$')) {
            $rate->error($this->_('Wrong format! Please use decimal with a dot (.) as separator e.g. 2.5'));
        }

        $alternatePrice = $form->get('alternatePrice');
        $alternatePriceValue = $alternatePrice->value;

        $shippingDescription = $form->get('shippingDescription');
        $shippingDescriptionValue = $shippingDescription->value;

        $shippingCost = $form->get('shippingCost');
        $shippingCostValue = $shippingCost->value;
        if ($shippingCostValue && !checkPattern($shippingCostValue, '^[-+]?[0-9]*[.]?[0-9]+$')) {
            $shippingCost->error($this->_('Wrong format! Please use decimal with a dot (.) as separator e.g. 4.5'));
        }

        $shippingGuaranteedDaysToDelivery = $form->get('shippingGuaranteedDaysToDelivery');
        $shippingGuaranteedDaysToDeliveryValue = $shippingGuaranteedDaysToDelivery->value;




        $trigger = $form->get('trigger');
        $triggerValue = $trigger->value;



        if ($form->getErrors()) {
            // The form is processed and populated but contains errors
            return $form->render();
        }

        // Sanitize and prepare input for saving
        $fieldValues = array(
            'name' => $nameValue,
            'expires' => $sanitizer->date($expiresValue, $expiresDateFormat) . 'T23:00:00Z',
            'maxNumberOfUsages' => $sanitizer->int($maxNumberOfUsagesValue),
            'currency' => $sanitizer->text($currencyValue),
            'combinable' => $combinableValue,
            'type' => $sanitizer->text($typeValue),
            'amount' => $sanitizer->text($amountValue), // don't santize to float because we always need . as decimal separator
            'rate' => $sanitizer->text($rateValue), // don't santize to float because we always need . as decimal separator
            'alternatePrice' => $sanitizer->text($alternatePriceValue),
            'shippingDescription' => $sanitizer->text($shippingDescriptionValue),
            'shippingCost' => $sanitizer->text($shippingCostValue), // don't santize to float because we always need . as decimal separator
            'shippingGuaranteedDaysToDelivery' => $sanitizer->text($shippingGuaranteedDaysToDeliveryValue),

            
            'trigger' => $sanitizer->text($triggerValue),
            
        );
        
        bd($fieldValues);

        /*
        $statusValue = $sanitizer->text($statusValue);
        $trackingNumberValue = $sanitizer->text($trackingNumberValue);
        $trackingUrlValue = $sanitizer->httpUrl($trackingUrlValue);
        $deliveryMethodValue = $sanitizer->option($deliveryMethodValue, array('Email', 'None'));

        if ($mode == 'edit') {
            $success = $this->_updateDiscount($id, $fieldValues);
        } else {
            $success = $this->_createDiscount($fieldValues);
        }

        if ($success) {
            // Reset cache for this order and redirect to itself to display updated values
            $this->wire('sniprest')->deleteDiscountCache($id);
            $redirectUrl = $this->currentUrl . '?modal=1';
            if ($ret) $redirectUrl .= '&ret=' . urlencode($ret);
            $session->redirect($redirectUrl);
        }
        */

        return $form->render();
    }

 

 

Link to comment
Share on other sites

Oh damn - I have it!

just add this line before processing input:

        // Manually write values for disabled fields to WireInputData before processing form input
        $input->post->set('type_disabled', $input->post->type);
        
        $form->processInput($input->post);

It's that easy! ProcessWire rocks!

Link to comment
Share on other sites

Here is the complete code - now with working simulated "readonly" InputfieldSelect:

Spoiler

    /**
     * Render and process the discount form.
     * (Edit or Add)
     *
     * @param array $item (optional)
     * @param string $ret A return URL (optional)
     * @return markup 
     *
     */
    private function _processDiscountForm($item = null, $ret = '') {
        $modules = $this->wire('modules');
        $sanitizer = $this->wire('sanitizer');
        $input = $this->wire('input');
        $session = $this->wire('session');

        $mode = ($item) ? 'edit' : 'add';

        $expiresDateFormat = 'Y-m-d';
        $expiresPlaceholder = 'YYYY-MM-DD';
        $expiresMinDate = wireDate($expiresDateFormat);
        
        if (!$input->post->saving_discount_active) {

            if ($mode == 'edit') {
                // Get values from payload
                $discount = array(
                    'id' => $item['id'],
                    'name' => $item['name'],
                    'expires' => $item['expires'],
                    'maxNumberOfUsages' => $item['maxNumberOfUsages'],
                    'currency' => (isset($item['currency']) ? $item['currency'] : ''), // currency field isn't always present
                    'combinable' => $item['combinable'],
                    'type' => $item['type'],
                    'type_disabled' => $item['type'], // needed to simulate a readonly select in edit mode
                    'amount' => $item['amount'],
                    'rate' => $item['rate'],
                    'alternatePrice' => $item['alternatePrice'],
                    'shippingDescription' => $item['shippingDescription'],
                    'shippingCost' => $item['shippingCost'],
                    'shippingGuaranteedDaysToDelivery' => $item['shippingGuaranteedDaysToDelivery'],
                    
                    
                    'trigger' => $item['trigger'],
                    'trigger_disabled' => $item['trigger'], // needed to simulate a readonly select in edit mode
                );
            } else {
                // Set default values (if action = add)
                $discount = array(
                    'id' => '',
                    'name' => '',
                    'expires' => '',
                    'maxNumberOfUsages' => 1,
                    'currency' => '',
                    'combinable' => '1',
                    'type' => 'FixedAmount',
                    'amount' => '',
                    'rate' => '',
                    'alternatePrice' => '',
                    'shippingDescription' => '',
                    'shippingCost' => '',
                    'shippingGuaranteedDaysToDelivery' => '',
                    
                    
                    'trigger' => 'Code',
                );
            }
        }

		/** @var InputfieldForm $form */
        $form = $modules->get('InputfieldForm');
        $form->attr('id', 'DiscountForm');
		$form->attr('action', $this->currentUrl);
        $form->attr('method', 'post');

            if ($ret) {
                /** @var InputfieldHidden $f */
                $f = $modules->get('InputfieldHidden');
                $f->attr('name', 'ret');
                $f->attr('value', urlencode($ret));
    
                $form->add($f);
            }

            /** @var InputfieldHidden $f */
    		$f = $modules->get('InputfieldHidden');
            $f->attr('name', 'saving_discount_active');
            $f->attr('value', true);

        $form->add($f);

            /** @var InputfieldHidden $f */
            $f = $modules->get('InputfieldHidden');
            $f->attr('name', 'id');

        $form->add($f);

            /** @var InputfieldFieldset $fieldset */
            $fieldset = $modules->get('InputfieldFieldset');
            $fieldset->label = $this->_('General Information');
            $fieldset->icon = 'info-circle';

        $form->add($fieldset);

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'name');
            $f->label = $this->_('Discount name');
            $f->required = true;
            $f->columnWidth = 50;

        $fieldset->add($f);
            
            /** @var InputfieldDatetime $f */
            $f = $modules->get('InputfieldDatetime');
            $f->attr('name', 'expires');
            $f->attr('placeholder', $expiresPlaceholder);
            $f->label = $this->_('Expires');
            $f->detail = $this->_('Leave empty to never expire');
            $f->size = 100;
            $f->datepicker = InputfieldDatetime::datepickerFocus;
            $f->dateInputFormat = $expiresDateFormat;
            $f->columnWidth = 50;

        $fieldset->add($f);

            /** @var InputfieldInteger $f */
            $f = $modules->get('InputfieldInteger');
            $f->attr('name', 'maxNumberOfUsages');
            $f->label = $this->_('Maximum number of usages');
            $f->detail = $this->_('Leave empty to enable unlimited usage');
            $f->size = 100;
            $f->min = 1;
            $f->columnWidth = 50;

        $fieldset->add($f);

            /** @var InputfieldSelect $f */
            $f = $modules->get('InputfieldSelect');
            $f->attr('name', 'currency');
            $f->label = $this->_('Currency');
            $f->columnWidth = 50;
            $supportedCurrencies = CurrencyFormat::getSupportedCurrencies();
            foreach ($this->currencies as $currencyOption) {
                $currencyLabel = isset($supportedCurrencies[$currencyOption])
                    ? $supportedCurrencies[$currencyOption]
                    : $currencyOption;
                $f->addOption($currencyOption, $currencyLabel);
            }

        $fieldset->add($f);

            /** @var InputfieldCheckbox $f */
            $f = $modules->get('InputfieldCheckbox');
            $f->attr('name', 'combinable');
            $f->label = $this->_('Combination with other discounts allowed?');

        $fieldset->add($f);

            /** @var InputfieldFieldset $fieldset */
            $fieldset = $modules->get('InputfieldFieldset');
            $fieldset->label = $this->_('Choose Discount Actions');
            $fieldset->icon = 'cogs';
            $fieldset->set('themeOffset', 1);

        $form->add($fieldset);

            /** @var InputfieldSelect $f */
            $f = $modules->get('InputfieldSelect');
            if ($mode == 'edit') {
                // simulate a readonly select in edit mode
                $f->attr('name', 'type_disabled');
                $f->attr('disabled', 'disabled');
            } else {
                $f->attr('name', 'type');
            }
            $f->addClass('InputfieldMaxWidth');
            $f->label = $this->_('Type');
            $f->required = true;
            $f->addOptions($this->getDiscountsTypes());

        $fieldset->add($f);

            if ($mode == 'edit') {
                // needed to simulate a readonly select in edit mode
                /** @var InputfieldHidden $f */
                $f = $modules->get('InputfieldHidden');
                $f->attr('name', 'type');

                $fieldset->add($f);
            }

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'amount');
            $f->attr('pattern', '[-+]?[0-9]*[.]?[0-9]+');
            $f->label = $this->_('Amount');
            $f->detail = $this->_('Decimal with a dot (.) as separator e.g. 19.99');
            $f->required = true;
            $f->showIf = 'type=FixedAmount|FixedAmountOnItems|FixedAmountOnCategory|AmountOnSubscription';
            $f->requiredIf = 'type=FixedAmount|FixedAmountOnItems|FixedAmountOnCategory|AmountOnSubscription';

        $fieldset->add($f);

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'rate');
            $f->attr('pattern', '[-+]?[0-9]*[.]?[0-9]+');
            $f->label = $this->_('Rate in %');
            $f->detail = $this->_('Decimal with a dot (.) as separator e.g. 2.5');
            $f->required = true;
            $f->showIf = 'type=Rate|RateOnItems|RateOnCategory|RateOnSubscription';
            $f->requiredIf = 'type=Rate|RateOnItems|RateOnCategory|RateOnSubscription';

        $fieldset->add($f);

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'alternatePrice');
            $f->label = $this->_('Alternate price list');
            $f->detail = $this->_('The name of the alternate price list to use');
            $f->required = true;
            $f->showIf = 'type=AlternatePrice';
            $f->requiredIf = 'type=AlternatePrice';

        $fieldset->add($f);

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'shippingDescription');
            $f->label = $this->_('Shipping description');
            $f->detail = $this->_('The shipping method name that will be displayed to your customers');
            $f->required = true;
            $f->showIf = 'type=Shipping';
            $f->requiredIf = 'type=Shipping';

        $fieldset->add($f);

            /** @var InputfieldText $f */
            $f = $modules->get('InputfieldText');
            $f->attr('name', 'shippingCost');
            $f->attr('pattern', '[-+]?[0-9]*[.]?[0-9]+');
            $f->label = $this->_('Shipping amount');
            $f->detail = $this->_('Decimal with a dot (.) as separator e.g. 4.5');
            $f->required = true;
            $f->showIf = 'type=Shipping';
            $f->requiredIf = 'type=Shipping';
            $f->columnWidth = 50;

        $fieldset->add($f);

            /** @var InputfieldInteger $f */
            $f = $modules->get('InputfieldInteger');
            $f->attr('name', 'shippingGuaranteedDaysToDelivery');
            $f->label = $this->_('Guaranteed days to delivery');
            $f->detail = $this->_('The number of days it will take for shipping (can be empty)');
            $f->size = 100;
            $f->min = 1;
            $f->showIf = 'type=Shipping';
            $f->columnWidth = 50;

        $fieldset->add($f);







            /** @var InputfieldFieldset $fieldset */
            $fieldset = $modules->get('InputfieldFieldset');
            $fieldset->label = $this->_('Choose Discount Conditions');
            $fieldset->icon = 'scissors';

        $form->add($fieldset);

            /** @var InputfieldSelect $f */
            $f = $modules->get('InputfieldSelect');
            if ($mode == 'edit') {
                // simulate a readonly select in edit mode
                $f->attr('name', 'trigger_disabled');
                $f->attr('disabled', 'disabled');
            } else {
                $f->attr('name', 'trigger');
            }
            $f->addClass('InputfieldMaxWidth');
            $f->label = $this->_('Trigger');
            $f->required = true;
            $f->addOptions($this->getDiscountsTriggers());

        $fieldset->add($f);

            if ($mode == 'edit') {
                // needed to simulate a readonly select in edit mode
                /** @var InputfieldHidden $f */
                $f = $modules->get('InputfieldHidden');
                $f->attr('name', 'trigger');

                $fieldset->add($f);
            }







            /** @var InputfieldSubmit $btn */
            $btn = $modules->get('InputfieldSubmit');
            $btn->attr('id', 'SaveDiscountButton');
            $btn->attr('name', 'save_discount');
            $btn->attr('value', $this->_('Save discount'));

        $form->add($btn);

        // Render form without processing if not submitted
        if (!$input->post->saving_discount_active) {
            $form->populateValues($discount);
            return $form->render();
        }
        
        // Manually write values for disabled fields to WireInputData before processing form input
        $input->post->set('type_disabled', $input->post->type);
        $input->post->set('trigger_disabled', $input->post->trigger);
        
        $form->processInput($input->post);

        // Get values and validate input
        $name = $form->get('name');
        $nameValue = $name->value;

        $expires = $form->get('expires');
        $expiresValue = $expires->value;
        if ($mode == 'add' && $expiresValue && !$sanitizer->date($expiresValue, $expiresDateFormat, array('min' => $expiresMinDate))) {
            $expires->error(sprintf($this->_('Minimum allowed date is %s (today)'), $expiresMinDate));
        }

        $maxNumberOfUsages = $form->get('maxNumberOfUsages');
        $maxNumberOfUsagesValue = $maxNumberOfUsages->value;

        $currency = $form->get('currency');
        $currencyValue = $currency->value;

        $combinable = $form->get('combinable');
        $combinableValue = $combinable->value;

        $type = $form->get('type');
        $typeValue = $type->value;

        $amount = $form->get('amount');
        $amountValue = $amount->value;
        if ($amountValue && !checkPattern($amountValue, '^[-+]?[0-9]*[.]?[0-9]+$')) {
            $amount->error($this->_('Wrong format! Please use decimal with a dot (.) as separator e.g. 19.99'));
        }

        $rate = $form->get('rate');
        $rateValue = $rate->value;
        if ($rateValue && !checkPattern($rateValue, '^[-+]?[0-9]*[.]?[0-9]+$')) {
            $rate->error($this->_('Wrong format! Please use decimal with a dot (.) as separator e.g. 2.5'));
        }

        $alternatePrice = $form->get('alternatePrice');
        $alternatePriceValue = $alternatePrice->value;

        $shippingDescription = $form->get('shippingDescription');
        $shippingDescriptionValue = $shippingDescription->value;

        $shippingCost = $form->get('shippingCost');
        $shippingCostValue = $shippingCost->value;
        if ($shippingCostValue && !checkPattern($shippingCostValue, '^[-+]?[0-9]*[.]?[0-9]+$')) {
            $shippingCost->error($this->_('Wrong format! Please use decimal with a dot (.) as separator e.g. 4.5'));
        }

        $shippingGuaranteedDaysToDelivery = $form->get('shippingGuaranteedDaysToDelivery');
        $shippingGuaranteedDaysToDeliveryValue = $shippingGuaranteedDaysToDelivery->value;




        $trigger = $form->get('trigger');
        $triggerValue = $trigger->value;



        if ($form->getErrors()) {
            // The form is processed and populated but contains errors
            return $form->render();
        }

        // Sanitize and prepare input for saving
        $fieldValues = array(
            'name' => $nameValue,
            'expires' => $sanitizer->date($expiresValue, $expiresDateFormat) . 'T23:00:00Z',
            'maxNumberOfUsages' => $sanitizer->int($maxNumberOfUsagesValue),
            'currency' => $sanitizer->text($currencyValue),
            'combinable' => $combinableValue,
            'type' => $sanitizer->text($typeValue),
            'amount' => $sanitizer->text($amountValue), // don't santize to float because we always need . as decimal separator
            'rate' => $sanitizer->text($rateValue), // don't santize to float because we always need . as decimal separator
            'alternatePrice' => $sanitizer->text($alternatePriceValue),
            'shippingDescription' => $sanitizer->text($shippingDescriptionValue),
            'shippingCost' => $sanitizer->text($shippingCostValue), // don't santize to float because we always need . as decimal separator
            'shippingGuaranteedDaysToDelivery' => $sanitizer->text($shippingGuaranteedDaysToDeliveryValue),

            
            'trigger' => $sanitizer->text($triggerValue),
            
        );
        
        bd($fieldValues);

        /*
        $statusValue = $sanitizer->text($statusValue);
        $trackingNumberValue = $sanitizer->text($trackingNumberValue);
        $trackingUrlValue = $sanitizer->httpUrl($trackingUrlValue);
        $deliveryMethodValue = $sanitizer->option($deliveryMethodValue, array('Email', 'None'));

        if ($mode == 'edit') {
            $success = $this->_updateDiscount($id, $fieldValues);
        } else {
            $success = $this->_createDiscount($fieldValues);
        }

        if ($success) {
            // Reset cache for this order and redirect to itself to display updated values
            $this->wire('sniprest')->deleteDiscountCache($id);
            $redirectUrl = $this->currentUrl . '?modal=1';
            if ($ret) $redirectUrl .= '&ret=' . urlencode($ret);
            $session->redirect($redirectUrl);
        }
        */

        return $form->render();
    }

 

 

  • Like 1
Link to comment
Share on other sites

On 1/2/2020 at 6:08 PM, Gadgetto said:

Some fields like the documented field below in code (near the middle of the code), needs to be readonly in edit mode as not all parts of a SnipCart discount can be changed after creation.

Why do you need to post values, which are no longer editable though? Should this not work just fine with the field disabled / not rendered as inoutfield?

  • Like 1
Link to comment
Share on other sites

7 hours ago, LostKobrakai said:

Why do you need to post values, which are no longer editable though? Should this not work just fine with the field disabled / not rendered as inoutfield?

The REST API of SnipCart requires this value with each POST or PUT request, but it may not be changed once submitted.

Link to comment
Share on other sites

40 minutes ago, flydev said:

@Gadgetto maybe I have misread you and/or you didn't tested the technique I told you, check this demo :  https://codepen.io/flydev/pen/ZEYvYKZ

 

Thanks for you input @flydev, I did check the technique you posted, but IMHO it's not very UX friendly. It first makes the user think that he can choose an option.

I solved it in an easy way by disabling the select and an additional hidden field (as posted above).

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...