I want to create ui component with tabs.
I want to my base data shows in general tabs and additional in next.
ui component
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">my_blog_form.my_blog_listing_data_source</item>
<item name="deps" xsi:type="string">my_blog_form.my_blog_listing_data_source</item>
</item>
<item name="label" xsi:type="string" translate="true">General</item>
<item name="layout" xsi:type="array">
<item name="type" xsi:type="string">tabs</item>
<item name="navContainerName" xsi:type="string">left</item>
</item>
<item name="buttons" xsi:type="array">
<item name="save" xsi:type="array">
<item name="name" xsi:type="string">save</item>
<item name="label" xsi:type="string" translate="true">Save</item>
<item name="class" xsi:type="string">primary</item>
<item name="url" xsi:type="string">*/*/save</item>
</item>
</item>
</argument>
<dataSource name="my_blog_form_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">MY\Blog\Ui\DataProvider</argument>
<argument name="name" xsi:type="string">my_blog_form_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">id</argument>
<argument name="requestFieldName" xsi:type="string">id</argument>
<argument name="collectionFactory" xsi:type="object">
\MY\Blog\Model\Post\ResourceModel\Post\CollectionFactory
</argument>
</argument>
</dataSource>
<fieldset name="general">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Sample Fieldset</item>
</item>
</argument>
<!-- This field has data type 'text' and standard 'input' form element and looks like input -->
<field name="title">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string">Title</item>
<item name="visible" xsi:type="boolean">true</item>
<item name="dataType" xsi:type="string">text</item>
<item name="formElement" xsi:type="string">input</item>
<item name="source" xsi:type="string">title</item>
</item>
</argument>
</field>
</fieldset>
</form>
Corresponding dataSource
<?php
namespace MY\Blog\Ui;
use Magento\Ui\DataProvider\AbstractDataProvider;
use \My\Blog\Model\Post\ResourceModel\Post\CollectionFactory;
class DataProvider extends AbstractDataProvider
{
protected $collection;
public function __construct(
$name,
$primaryFieldName,
$requestFieldName,
CollectionFactory $collectionFactory,
array $meta = [],
array $data = []
) {
parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
$this->collection = $collectionFactory->create();
}
public function getData()
{
return [];
$results = [];
// var_dump($this->collection->getItems());die();
foreach ($this->collection->getItems() as $item) {
$results[$item->getId()]['general'] = $item->getData();
}
return $results;
}
}
I don't see any tabs and spinner never stops. What am I missing here I got 0 console errors. Model works because I have working data grid that shows my data.
Add this in your form XML
<settings>
<deps>
<dep>my_blog_form.my_blog_listing_data_source</dep>
</deps>
<layout>
<navContainerName>left</navContainerName>
<type>tabs</type>
</layout>
</settings>
set layout 2-column left like this
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<uiComponent name="your_form_name" />
</referenceContainer>
</body>
</page>
I have and issue with empty form fields when I'm using tabs.
If I removing tabs usage, fields contains correct values.
My form uicomponent is large, so I will paste only important parts of configuration:
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">vendor_modulename_form.vendor_modulename_form_data_source</item>
</item>
<item name="label" xsi:type="string" translate="true">Item</item>
...
</argument>
<settings>
...
<namespace>vendor_modulename_form</namespace>
<dataScope>data</dataScope>
<deps>
<dep>vendor_modulename_form.vendor_modulename_form_data_source</dep>
</deps>
<layout>
<navContainerName>left</navContainerName>
<type>tabs</type>
</layout>
</settings>
<fieldset name="modules">
<settings>
<collapsible>true</collapsible>
<opened>true</opened>
<label translate="true">Details</label>
</settings>
<field name="name" formElement="input">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="source" xsi:type="string">module</item>
</item>
</argument>
<settings>
<dataType>text</dataType>
<label translate="true">Name</label>
<dataType>text</dataType>
<visible>true</visible>
<dataScope>name</dataScope>
</settings>
</field>
...
</fieldset>
Console log and magento logs are empty. I'm working in developer mode.
Any ideas?
In the dataprovider you have to wrap all the content of your fieldset with the key after loading the data.
Eg:
$id = $this->request->getParam('id');
/** #var Collection $items */
$items = $this->collectionFactory->create()->addFieldToFilter('id', $id)->getItems();
foreach ($items as $item) {
$formData['modules'] = $item->getData();
$this->loadedData[$item->getId()] = $formData;
}
I tried to show the shipping country in the Admin Sales Order Grid but nothing works.
I did check the customer address configuration twice and there I can see that the country variable exists and should be shown. But in the grid you can not see the shipping country.
Any workarounds?
I found a solution. Creating a Module and Rewrite Class.
app/code/Vendor/ExtendedAdminGrid/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
<arguments>
<argument name="collections" xsi:type="array">
<item name="sales_order_grid_data_source" xsi:type="string">Vendor\ExtendedAdminGrid\Model\ResourceModel\Order\Grid\Collection</item>
</argument>
</arguments>
</type>
</config>
app/code/Vendor/ExtendedAdminGrid/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Vendor_ExtendedAdminGrid" setup_version="2.0.0">
<sequence>
<module name="Magento_Sales"/>
<module name="Magento_Backend"/>
</sequence>
</module>
</config>
app/code/Vendor/ExtendedAdminGrid/Model/ResourceModel/Order/Grid/Collection.php
<?php
namespace Vendor\ExtendedAdminGrid\Model\ResourceModel\Order\Grid;
class Collection extends \Magento\Sales\Model\ResourceModel\Order\Grid\Collection
{
protected function _renderFiltersBefore()
{
$this->getSelect()->joinLeft(
["soa" => "sales_order_address"],
"main_table.entity_id = soa.parent_id and soa.address_type = 'shipping'",
array('country_id')
)
->distinct();
parent::_renderFiltersBefore();
}
protected function _initSelect()
{
$this->addFilterToMap('created_at', 'main_table.created_at');
$this->addFilterToMap('base_grand_total', 'main_table.base_grand_total');
$this->addFilterToMap('grand_total', 'main_table.grand_total');
$this->addFilterToMap('store_id', 'main_table.store_id');
$this->addFilterToMap('store_name', 'main_table.store_name');
$this->addFilterToMap('order_id', 'main_table.order_id');
$this->addFilterToMap('order_increment_id', 'main_table.order_increment_id');
$this->addFilterToMap('billing_name', 'main_table.billing_name');
$this->addFilterToMap('billing_name', 'main_table.shipping_name');
$this->addFilterToMap('status', 'main_table.status');
parent::_initSelect();
}
}
app/code/Vendor/ExtendedAdminGrid/view/adminhtml/ui_component/sales_order_grid.xml
<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<columns name="sales_order_columns">
<column name="country_id">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">text</item>
<item name="label" xsi:type="string" translate="true">Shipping Country ID</item>
</item>
</argument>
</column>
</columns>
</listing>
app/code/Vendor/ExtendedAdminGrid/registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Vendor_ExtendedAdminGrid',
__DIR__
);
Thanks to Sergey for this great blogpost Modifying the default magento2 sales order grid — adding a coupon code column.
I am new to Orbeon and trying to implement a dynamic dropdown where the values are populated from a lookup xml on file system.
So here's the requirement:
The first dropdown (Animal) will have 2 values: Cat and Dog. Based on the selection, the second dropdown (Breeds) will display the list of breeds.
The 2 xml files containing the breeds are registered as resources and look like this:
CAT: \forms\quote\lookup\catbreeds.xml
<?xml version="1.0" encoding="UTF-8"?>
<breeds>
<item>
<value>C1</value>
<label>Domestic Long Hair</label>
</item>
<item>
<value>C2</value>
<label>Domestic Medium Hair</label>
</item>
<item>
<value>C3</value>
<label>Domestic Short Hair</label>
</item>
<item>
<value>C4</value>
<label>Mixed Breed</label>
</item>
<item>
<value>C5</value>
<label>Tabby</label>
</item>
<item>
<value>C6</value>
<label>Abyssinian</label>
</item>
<item>
<value>C7</value>
<label>American Bobtail</label>
</item>
</breeds>
DOG: \forms\quote\lookup\dogbreeds.xml
<?xml version="1.0" encoding="UTF-8"?>
<breeds>
<item>
<value>D1</value>
<label>Cavapoo</label>
</item>
<item>
<value>D2</value>
<label>Cockapoo</label>
</item>
<item>
<value>D3</value>
<label>Crossbreed</label>
</item>
<item>
<value>D4</value>
<label>Goldendoodle</label>
</item>
<item>
<value>D5</value>
<label>Labradoodle</label>
</item>
<item>
<value>D6</value>
<label>Maltipoo</label>
</item>
<item>
<value>D7</value>
<label>Mi Ki</label>
</item>
</breeds>
The form.xml looks like this:
Model:
<xf:instance id="fr-form-instance" xxf:exclude-result-prefixes="#all">
<form>
<section-1>
<animal/>
<breed/>
</section-1>
</form>
</xf:instance>
<xf:instance id="pets"
xmlns="">
<root>
<item name="Cat" value="cat"/>
<item name="Dog" value="dog"/>
</root>
</xf:instance>
Body:
<xh:body>
<fr:view>
<fr:body
xmlns:oxf="http://www.orbeon.com/oxf/processors"
xmlns:p="http://www.orbeon.com/oxf/pipeline"
xmlns:xbl="http://www.w3.org/ns/xbl">
<fr:section id="section-1-control" class="no-header-section" bind="section-1-bind">
<fr:grid>
<xh:tr>
<xh:td>
<fr:dropdown-select1 id="animal-control" ref="animal" bind="breed-bind">
<xf:label ref="$form-resources/animal/label"/>
<xf:itemset ref="instance('pets')/item">
<xf:label ref="#name"/>
<xf:value ref="#value"/>
</xf:itemset>
</fr:dropdown-select1>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<fr:dropdown-select1 id="breed-control" bind="breed-bind">
<xf:label ref="$form-resources/breed/label"/>
<xf:itemset
ref="doc('oxf:/forms/quote/lookup/catbreeds.xml')/breeds/item">
<xf:label ref="label"/>
<xf:value ref="value"/>
</xf:itemset>
</fr:dropdown-select1>
</xh:td>
</xh:tr>
</fr:grid>
</fr:section>
</fr:body>
</fr:view>
</xh:body>
Now, the "ref" attribute in ref="doc('oxf:/forms/quote/lookup/catbreeds.xml')/breeds/item"> is where the problem is. I am able to load the individual lists (in this case it loads Cat breeds) but I am not able to find a way to make it conditional.
I found that I cannot use XPath for ref (like this:oxf:/forms/quote/lookup/{animal}breeds.xml) to make the value dynamic.
I have been trying a lot of things but nothing is working out. It will be a great help if someone can give me a direction.
I'm on Orbeon 4.8
Since the value of ref is XPath, you can build the URL you pass to doc() dynamically, by doing something along these lines:
doc(concat(
'oxf:/forms/quote/lookup/',
instance('fr-form-instance')/section-1/animal,
'breeds.xml'
))/breeds/item
I get this error when I run my vxml app;
"ECMAScript runtime error: Compilation produced 1 syntax
errors.\n\nWhile evaluating:\n\"var acc_no = [37492414, 94190610,
23228367, 39574988, 64742440];\n\t\t\t\t\tfunction checkAccount(arr,
val) {\n\t\t\t\t\treturn arr.some(arrVal => val ===
arrVal);\n\t\t\t\t\t\t\t\t\t\t\t} \"";
Here's my vxml script where the error arises:
<?xml version="1.0" encoding="UTF-8"?>
<vxml xmlns:voxeo="http://community.voxeo.com/xmlns/vxml"
version="2.1" xml:lang="en-US"
xml:base="http://webhosting.voxeo.net/201985/www/">
<property name="inputmodes" value="dtmf"/>
<property name="termchar" value="#"/>
<property name="interdigittimeout" value="2s"/>
<property name="bargein" value="false"/>
<var name = "accountNumber"/>
<var name = "pinNumber"/>
<form id="userAuth" scope="document">
<var name="iMaxTries" expr="3"/>
<var name="iTriesAcc" expr="0"/>
<var name="iTriesPin" expr="0"/>
<var name="fatal" expr="'We are having technical difficulties validating your credentials. Try back later.'"/>
<catch event="event.pinNumber.invalid">
<!-- increment the attempt counter; if the count is exceeded, disconnect -->
<assign name="iTriesPin" expr="iTriesPin+1"/>
<if cond="iMaxTries == iTries">
<value expr="fatal"/>
<disconnect/>
<else/>
<!-- clear is unnecessary on a nomatch, but we use the same code to handle a bad filled -->
<clear namelist="pinNumber"/>
<reprompt/>
</if>
</catch>
<catch event="event.accountNumber.invalid">
<!-- increment the attempt counter; if the count is exceeded, disconnect -->
<assign name="iTriesAcc" expr="iTriesAcc+1"/>
<if cond="iMaxTries == iTries">
<value expr="fatal"/>
<disconnect/>
<else/>
<!-- clear is unnecessary on a nomatch, but we use the same code to handle a bad filled -->
<clear namelist="accountNumber"/>
<reprompt/>
</if>
</catch>
<!-- exec this on the first and second noinput/nomatch -->
<!-- each event has its own counter -->
<catch event="noinput">
I'm sorry. I didn't get you.
<reprompt />
</catch>
<!-- exec this on the third nomatch -->
<catch event="nomatch">
<throw event="event.password.invalid"/>
</catch>
<!-- silently disconnect on the third noinput -->
<catch event="noinput" count="3">
<disconnect/>
</catch>
<field name="accountNumber" type="digits?length=8">
<prompt> Please enter your account number followed by the pound key. </prompt>
<grammar mode="dtmf" version="1.0" root="pin"
tag-format="semantics/1.0">
<rule id="digit" scope="public" >
<one-of>
<item> 0 </item>
<item> 1 </item>
<item> 2 </item>
<item> 3 </item>
<item> 4 </item>
<item> 5 </item>
<item> 6 </item>
<item> 7 </item>
<item> 8 </item>
<item> 9 </item>
</one-of>
</rule>
<rule id="pin" scope="public">
<tag>out=""</tag>
<item repeat="8">
<ruleref uri="#digit"/>
<tag>out += rules.latest( );</tag>
</item>
</rule>
</grammar>
<filled>
<script> <![CDATA[
var acc_no = [37492414, 94190610, 23228367, 39574988, 64742440];
function checkAccount(arr, val) {
return arr.some(arrVal => val === arrVal);
}
]]> </script>
<block>
<var name="chk_acc" expr="checkAccount(acc_no, accountNumber);"/>
<if cond="chk_acc =='true'">
<goto next="#pinNumber"/>
<else/>
<prompt>Sorry, Account number not recognised. </prompt>
<throw event="event.accountNumber.invalid"/>
</if>
</block>
</filled>
</field>
<field name="pinNumber" type="digits?length=4">
<prompt> please enter your four digit pin followed by the pound key. </prompt>
<grammar mode="dtmf" version="1.0" root="pin"
tag-format="semantics/1.0">
<rule id="digit" scope="public" >
<one-of>
<item> 0 </item>
<item> 1 </item>
<item> 2 </item>
<item> 3 </item>
<item> 4 </item>
<item> 5 </item>
<item> 6 </item>
<item> 7 </item>
<item> 8 </item>
<item> 9 </item>
</one-of>
</rule>
<rule id="pin" scope="public">
<tag>out=""</tag>
<item repeat="4">
<ruleref uri="#digit"/>
<tag>out += rules.latest( );</tag>
</item>
</rule>
</grammar>
<filled>
<script> <![CDATA[
var pin_no = [2414, 0610,8367, 4988, 2440];
function checkPin(arr, val) {
return arr.some(arrVal => val === arrVal);
}
]]> </script>
<block>
<var name="chk_pin" expr="checkPin(pin_no, pinNumber);"/>
<if cond="chk_pin =='false'">
<prompt>Sorry, you have entered is an invalid pin. Please try again </prompt>
<throw event="event.pinNumber.invalid"/>
</if>
</block>
</filled>
</field>
<filled mode="all" namelist="accountNumber pinNumber">
<script> <![CDATA[
var accDetails = [
{acc_name: 'Lawrence Burkins', account: 37492414, pin: 2414, acc_type: 'checking', acc_bal: 2372351.74 , acc_br:'Montreal'},
{acc_name: 'Ola Macaulay', account: 94190610, pin: 0610, acc_type: 'checking', acc_bal: 908242.49 , acc_br:'Tisdale'},
{acc_name: 'Judy Cefalu', account: 23228367, pin: 8367, acc_type: 'checking', acc_bal: 15700526.57 , acc_br:'Toronto'},
{acc_name: 'Mellisa Garcia', account: 39574988, pin: 4988, acc_type: 'checking', acc_bal: 568201.26 , acc_br:'Prince Albert'},
{acc_name: '', account: 64742440, pin: 2440, acc_type: 'checking', acc_bal: 1952000.00 , acc_br:'Fort McMurray'},
];
function accDetails(details) {
return details.account === accountNumber ;
}
var newDetail = accDetails.find(accDetails);
var myDetail = [newDetail];
var myBal = myDetail.slice(0, 4);
]]> </script>
<var name = "accountBalance" expr = "myBal.toString()"/>
<prompt>
Your Checking account balance is <prosody rate="slow"><say-as type="currency"> $ + <value class="currency" expr="accountBalance"/> </say-as></prosody>
</prompt>
<goto next="after_bal.vxml"/>
</filled>
</form>
</vxml>
I am still new to vxml and ecmascript.
The ECMAScript in question seems to be syntactically correct:
var acc_no = [37492414, 94190610, 23228367, 39574988, 64742440];
function checkAccount(arr, val) {
return arr.some(arrVal => val === arrVal);
}
I would suggest breaking this piecemeal and reduce the complexity of the VXML code to debug it. Use a very basic VXML file with one simple field, put the above ECMAScript in the filled section and then see if you get the same error. If you do, move the script further up in the code (i.e not in the filled section) and again check if you get the same error.
The error statement is a bit confusing because of the linefeeds etc. Does the error message look like that when you see it the first time?