Dropdown instead of input field
C4rter opened this issue · 7 comments
I really love your extension. It sheds some light in adding new fields to the checkout process.
Compared to Magento 1 this is a lot of pain. I don't understand why they had to make it much more complex to add new fields.
Do you know how a drop down instead of input field would work?
I know that "ui/form/element/select" shows me a drop down. But I can't figure out how to add options to this.
I got it working with defining the values in the XML according to the Magento example:
http://devdocs.magento.com/guides/v2.0/howdoi/checkout/checkout_form.html
But how would I get them from a model?
0. To add select input with option values you need to add following code and probably you found it already:
/* view/frontend/layout/checkout_index_index.xml */
<item name="select_field" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/element/select</item>
<item name="config" xsi:type="array">
<!--customScope is used to group elements within a single form (e.g. they can be validated separately)-->
<item name="customScope" xsi:type="string">customCheckoutForm</item>
<item name="template" xsi:type="string">ui/form/field</item>
<item name="elementTmpl" xsi:type="string">ui/form/element/select</item>
</item>
<item name="options" xsi:type="array">
<item name="0" xsi:type="array">
<item name="label" xsi:type="string">Please select value</item>
<item name="value" xsi:type="string"></item>
</item>
<item name="1" xsi:type="array">
<item name="label" xsi:type="string">Option 1</item>
<item name="value" xsi:type="string">value_1</item>
</item>
<item name="2" xsi:type="array">
<item name="label" xsi:type="string">Option 2</item>
<item name="value" xsi:type="string">value_2</item>
</item>
</item>
<!-- value element allows to specify default value of the form field -->
<item name="value" xsi:type="string">value_2</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="dataScope" xsi:type="string">customCheckoutForm.select_field</item>
<item name="label" xsi:type="string">Select Field</item>
<item name="sortOrder" xsi:type="string">2</item>
</item>
You need to add few more things as i described in README.md file.
Be aware that in above example option name is select_field
.
In a real case, you should name it e.g as new_name_select
.
What next?
1) Add declaration of new field to Api/Data/CustomFieldsInterfaces.php
. This is service contract data interface.
const CHECKOUT_NEW_NAME_SELECT = 'new_name_select';
// add here also setter and getter
/**
* Get new select name
*
* @return string|null
*/
public function getNewNameSelect();
/**
* Set new select name
*
* @param string|null $newNameSelect New Name Select
*
* @return CustomFieldsInterface
*/
public function setNewNameSelect(string $newNameSelect = null);
2) Implement new field logic:
// Model/Data/CustomFields.php
/**
* Get new select name
*
* @return string|null
*/
public function getNewNameSelect()
{
return $this->_get(self::CHECKOUT_NEW_NAME_SELECT );
}
/**
* Set new select name
*
* @param string|null $newNameSelect New Name Select
*
* @return CustomFieldsInterface
*/
public function setNewNameSelect(string $newNameSelect = null)
{
return $this->setData(self::CHECKOUT_NEW_NAME_SELECT , $newNameSelect);
}
3. Add a new field to your DB (to quota and order tables)
// Setup/InstallData.php
// in installQuoteData() method
$quoteInstaller
->addAttribute(
'quote',
CustomFieldsInterface::CHECKOUT_NEW_NAME_SELECT,
['type' => Table::TYPE_TEXT, 'length' => '255', 'nullable' => true]
);
// in installSalesData() method
$salesInstaller
->addAttribute(
'order',
CustomFieldsInterface::CHECKOUT_NEW_NAME_SELECT,
['type' => Table::TYPE_TEXT, 'length' => '255', 'nullable' => true, 'grid' => false]
);
4. Save new field value in quota
//Model/CustomFieldsRepository.php
$cart->setData(
CustomFieldsInterface::CHECKOUT_NEW_NAME_SELECT,
$customFields->getNewNameSelect()
);
5. Copy and save new field value to order
// Observer/AddCustomFieldsToOrder.php
$order->setData(
CustomFieldsInterface::CHECKOUT_NEW_NAME_SELECT,
$quote->getData(CustomFieldsInterface::CHECKOUT_NEW_NAME_SELECT)
);
6. Update frontend view for customer account
/* view/frontend/templates/order/view/custom_fields.phtml */
<strong><?php /* @escapeNotVerified */ echo __('New select name') ?>:</strong>
<?php echo $this->escapeHtml($customFields->getNewNameSelect()); ?><br>
7. Update frontend view for order details in admin panel
/* view/adminhtml/templates/order/view/custom_fields.phtml */
<div class="box">
<strong class="box-title"><span><?php /* @escapeNotVerified */ echo __('New select name') ?></span></strong>
<div class="box-content">
<?php echo $this->escapeHtml($customFields->getNewNameSelect()); ?>
</div>
</div>
@sbodak Yes I got it working with your example and the Magento description.
Thank you for your detailed answer.
I came across another thing:
How do you control where the additional fields appear?
I tried experimenting with different elements and positioning in the layout xml but it did not work very well. I managed to move it to the billing step for example but smaller changes did not work.
I wanted to place the fields below the shipping-address instead of above. I noticed this in your file:
<item name="shippingAddress" xsi:type="array">
<item name="children" xsi:type="array">
<item name="before-form" xsi:type="array">
And I tried "after-form" instead, but it did not work. I guess that's just a name and has nothing to do with placement?
You can check available default items in:
/vendor/magento/module-checkout/view/frontend/layout/checkout_index_index.xml
You can see there that before-form
is name of item.
<item name="shippingAddress" xsi:type="array">
...
<item name="children" xsi:type="array">
<item name="customer-email" xsi:type="array">
...
</item>
<item name="before-form" xsi:type="array">
...
</item>
<item name="before-fields" xsi:type="array">
...
</item>
<item name="address-list" xsi:type="array">
...
</item>
<item name="address-list-additional-addresses" xsi:type="array">
...
</item>
<item name="before-shipping-method-form" xsi:type="array">
...
</item>
<item name="shipping-address-fieldset" xsi:type="array">
...
</item>
</item>
</item>
Custom form is now set by default after Shipping address form.
@sbodak is there any "after-shipping-method-form"? I was trying to show block after shipment method list but its not showing however "before-shipping-method-form" works well.
And also want to show/hide this block after selection of particular shipment method.
Please help