You've asked a bit of a mouthful there -- probably too much for a single Stack Exchange question, so I'm going to concentrate on teaching you how to reset the initial state of the form so things no longer appear invalid if there's a blank value. If you're interested in the whys, you'll need to get up to speed on the fundamentals of UI Components and x-magento-init
scripts. My Magento 2 UI Components and uiElement Internals series are a good place to start. The following assumes you have some familiarity with these systems -- if there's something confusing below then the above articles (as well as the other Magento 2 articles) will probably have the information you're looking for.
In the Checkout Application, each form field is represented by a view model, and one-or-many view model templates. You can see this in Commerce Bug's KO Scopes tab.
The firstname's view model is an object derived from the constructor function returned by the Magento_Ui/js/form/element/abstract
RequireJS module. You can find that model's source code here
vendor/magento//module-ui/view/base/web/js/form/element/abstract.js
The reset
method is the one we're interested in. This will reset a field's validation state. You'll need to figure out the full uiRegistry
string identifier for the specific model (again, Commerce Bug is useful here), use that string to fetch the instantiated view model, and then call the reset function. For the checkmo
form, the following program (easily adapted into a define
module if you're going to use it in your application) will do that for the firstname
field.
requirejs(['uiRegistry'], function(uiRegistry){
uiRegistry.get('checkout.steps.billing-step.payment.payments-list.checkmo-form.form-fields.firstname').reset();
});
Of course, you'll likely want to fetch each view model that's part of a particular form -- the following is a start on that.
uiRegistry.get(function(viewModel){
var parentName = viewModel['parentName'] ? viewModel['parentName'] : '';
if(parentName.indexOf('checkout.steps.billing-step.payment.payments-list.checkmo-form.form-fields') === -1){
return;
};
console.log(viewModel);
});
This uses the uiRegistry
's callback feature to search for all view models with a parent of checkout.steps.billing-step.payment.payments-list.checkmo-form.form-fields
. Some of these may not be form elements, but we'll leave that problem as an exercise for the questioner.
Hope that helps!
The layout nodes for actual fields for the address are added the block methodMagento\Checkout\Block\Checkout\LayoutProcessor::process
. In order to move these dynamically added layout nodes, you have to write a plugin. This is well explained in the following Magento StackExchange post:
how to reorder (switch) billing address before shipping address
Best Answer
Just follow this path in checkout_index_index.xml
But you need to specify validators in each form. Or you can try to use layoutProcessor like here going through the loop and reffer to paymend method via its $keyCode.
Also I found that rule max_text_length does not work properly on billing forms but works perfectly in shipping forms. I ended up with creating own validation rule.
You can find all rules here Magento_Ui/js/lib/validation/rules.js
Be careful with rules form mage/validation.js they don't work on chekout and vice versa (please correct me if I am wrong) so it's the reason why I tried to use max_text_length instead of validate-length maximum-length-35