1) I'm trying to filter the customer addresses in the checkout according to their postal code. The address blocks are displayed using the following knockoutjs code:
vendor/magento/module-checkout/view/frontend/web/template/shipping-address/list.html
<!-- ko if: (visible)-->
<div class="field addresses">
 <div class="control">
 <div class="shipping-address-items">
 <!-- ko foreach: { data: elems, as: 'element' } -->
 <!-- ko template: element.getTemplate() --><!-- /ko -->
 <!-- /ko -->
 </div>
 </div>
</div>
<!-- /ko -->
First thing, I'm struggling to understand where the elems variable comes from. Where should I be looking for its declaration?
2) Then I've been able to retrieve the postcode from the element object, and add a comparison to a hardcoded value. The following code works, only displaying the addresses whose postal code is 12345:
<!-- ko foreach: { data: elems, as: 'element' } -->
 <!-- ko if: (element.address().postcode === "12345") -->
 <!-- ko template: element.getTemplate() --><!-- /ko -->
 <!-- /ko -->
<!-- /ko -->
But how can I pass a value from php or jQuery (or a knockoutjs selector?) to use as my comparison instead of the hardcoded string?
- 
 2Welcome to hell (the Magento 2 checkout), you must have been a bad person to get here.Ben Crook– Ben Crook2018年06月07日 14:43:40 +00:00Commented Jun 7, 2018 at 14:43
- 
 @BenCrook, Caught right one !!anonymous– anonymous2018年06月08日 12:14:50 +00:00Commented Jun 8, 2018 at 12:14
2 Answers 2
I've made some progress here, for some reason I expected the list.html to work with the list.js, but within the foreach tag I needed to use address-renderer/default.js
vendor/magento/module-checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js
In this file I've been able to declare a function returning the postal code I needed from the known quote object. In the list.html I've simply called this function in my condition, and it works (both files copied in my local theme).
<!-- ko foreach: { data: elems, as: 'element' } -->
 <!-- ko if: (element.address().postcode === getPostalcode()) -->
 <!-- ko template: element.getTemplate() --><!-- /ko -->
 <!-- /ko -->
<!-- /ko -->
So I still don't know where the elems variable comes from, but at least I've been able to retrieve my value from existing js objects!
Taken from https://devdocs.magento.com/guides/v2.1/ui_comp_guide/concepts/ui_comp_uicollection_concept.html
elems is the observable property that contains the collection of child UI components.
console.log(this.elems());
// [
// %uiComponentInstance 1 %,
// %uiComponentInstance 2 %,
// %uiComponentInstance 3 %,
// %uiComponentInstance 4 %
// ]
If you search for elems inside vendor/magento/module-ui/view/base/web/js/lib/core/collection.js you will find a few functions that can populate this collection. Such as:
- _insert- Inserts provided component into 'elems' array at a specified position.
- _updateCollection- Synchronizes multiple elements arrays with a core '_elems' container.
- insertChild- Requests specified components to insert them into 'elems' array starting from provided position.
I've also answered a similar question here that has a bit more info - Magento 2: What Populates "elems" in a UI Component
To pass data through to this I believe you'd need to extend and edit vendor/magento/module-checkout/view/frontend/layout/checkout_index_index.xml:160
<item name="address-list" xsi:type="array">
 <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-address/list</item>
 <item name="displayArea" xsi:type="string">address-list</item>
</item>
I haven't ever passed data in this way so I can't help much more here sorry. Hopefully this helps slightly.