Magento 2 - Adding a design configuration setting issue - magento2

Apologies if this question has been asked and answered already, or documentation provides a solution, but I can't seem to get my head around this.
My objective is to add a custom field within the design configuration settings, where an administrator can toggle enabling Christmas effects to the frontend store. From what I have read online, the best way to do this is via a custom module, though I may be wrong?
So I have created a module to add a design configuration setting (Set Christmas Theme). In the module's etc/di.xml file, I have added the following:
<?xml version="1.0"?>
<!--
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Theme\Model\Design\Config\MetadataProvider">
<arguments>
<argument name="metadata" xsi:type="array">
<item name="header_christmas_theme" xsi:type="array">
<item name="path" xsi:type="string">design/header/christmas_theme</item>
<item name="fieldset" xsi:type="string">other_settings/header</item>
<item name="componentType" xsi:type="string">field</item>
</item>
</argument>
</arguments>
</type>
</config>
Within the module's view/adminhtml/ui_component/design_config_form.xml file, I have added the following:
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<field name="header_christmas_theme">
<argument name="data" xsi:type="array">
<item name="options" xsi:type="object">Magento\Config\Model\Config\Source\Yesno</item>
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Set Christmas Theme</item>
<item name="dataType" xsi:type="string">text</item>
<item name="componentType" xsi:type="string">field</item>
<item name="formElement" xsi:type="string">select</item>
<item name="dataScope" xsi:type="string">header_christmas_theme</item>
<item name="value" xsi:type="string">0</item>
</item>
</argument>
</field>
</form>
When enabling the module, running setup:upgrade in console and clearing the cache, I get the error below. Can anyone assist on where I am going wrong with adding a custom field to the design configuration?
1 exception(s):
Exception #0 (Magento\Framework\Exception\LocalizedException): The configuration parameter "componentType" is a required for "header_christmas_theme" component.
Exception #0 (Magento\Framework\Exception\LocalizedException): The configuration parameter "componentType" is a required for "header_christmas_theme" component.
#0 /vendor/magento/framework/View/Element/UiComponentFactory.php(361): Magento\Framework\View\Element\UiComponentFactory->mergeMetadataItem(Array, Array, false)
#1 /vendor/magento/framework/View/Element/UiComponentFactory.php(361): Magento\Framework\View\Element\UiComponentFactory->mergeMetadataItem(Array, Array, false)
#2 /vendor/magento/framework/View/Element/UiComponentFactory.php(361): Magento\Framework\View\Element\UiComponentFactory->mergeMetadataItem(Array, Array, false)
#3 /vendor/magento/framework/View/Element/UiComponentFactory.php(272): Magento\Framework\View\Element\UiComponentFactory->mergeMetadataItem(Array, Array, false)
#4 /vendor/magento/framework/View/Element/UiComponentFactory.php(164): Magento\Framework\View\Element\UiComponentFactory->mergeMetadata('design_config_f...', Array, false)
#5 /vendor/magento/framework/View/Layout/Generator/UiComponent.php(124): Magento\Framework\View\Element\UiComponentFactory->create('design_config_f...', NULL, Array)
#6 /vendor/magento/framework/View/Layout/Generator/UiComponent.php(93): Magento\Framework\View\Layout\Generator\UiComponent->generateComponent(Object(Magento\Framework\View\Layout\Data\Structure), 'design_config_f...', Array, Object(Magento\Framework\View\Layout\Interceptor))
#7 /vendor/magento/framework/View/Layout/GeneratorPool.php(86): Magento\Framework\View\Layout\Generator\UiComponent->process(Object(Magento\Framework\View\Layout\Reader\Context), Object(Magento\Framework\View\Layout\Generator\Context))
#8 /vendor/magento/framework/View/Layout.php(327): Magento\Framework\View\Layout\GeneratorPool->process(Object(Magento\Framework\View\Layout\Reader\Context), Object(Magento\Framework\View\Layout\Generator\Context))
#9 /var/generation/Magento/Framework/View/Layout/Interceptor.php(89): Magento\Framework\View\Layout->generateElements()
#10 /vendor/magento/framework/View/Layout/Builder.php(129): Magento\Framework\View\Layout\Interceptor->generateElements()
#11 /vendor/magento/framework/View/Page/Builder.php(55): Magento\Framework\View\Layout\Builder->generateLayoutBlocks()
#12 /vendor/magento/framework/View/Layout/Builder.php(65): Magento\Framework\View\Page\Builder->generateLayoutBlocks()
#13 /vendor/magento/framework/View/Layout.php(244): Magento\Framework\View\Layout\Builder->build()
#14 /vendor/magento/framework/View/Layout.php(859): Magento\Framework\View\Layout->build()
#15 /var/generation/Magento/Framework/View/Layout/Interceptor.php(414): Magento\Framework\View\Layout->getBlock('menu')
#16 /vendor/magento/module-backend/Model/View/Result/Page.php(59): Magento\Framework\View\Layout\Interceptor->getBlock('menu')
#17 /var/generation/Magento/Backend/Model/View/Result/Page/Interceptor.php(24): Magento\Backend\Model\View\Result\Page->setActiveMenu('Magento_Theme::...')
#18 /vendor/magento/module-theme/Controller/Adminhtml/Design/Config/Edit.php(69): Magento\Backend\Model\View\Result\Page\Interceptor->setActiveMenu('Magento_Theme::...')
#19 /var/generation/Magento/Theme/Controller/Adminhtml/Design/Config/Edit/Interceptor.php(24): Magento\Theme\Controller\Adminhtml\Design\Config\Edit->execute()
#20 /vendor/magento/framework/App/Action/Action.php(102): Magento\Theme\Controller\Adminhtml\Design\Config\Edit\Interceptor->execute()
#21 /vendor/magento/module-backend/App/AbstractAction.php(226): Magento\Framework\App\Action\Action->dispatch(Object(Magento\Framework\App\Request\Http))
#22 /vendor/magento/framework/Interception/Interceptor.php(74): Magento\Backend\App\AbstractAction->dispatch(Object(Magento\Framework\App\Request\Http))
#23 /vendor/magento/framework/Interception/Chain/Chain.php(70): Magento\Theme\Controller\Adminhtml\Design\Config\Edit\Interceptor->___callParent('dispatch', Array)
#24 /vendor/magento/framework/Interception/Chain/Chain.php(63): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Theme\\C...', 'dispatch', Object(Magento\Theme\Controller\Adminhtml\Design\Config\Edit\Interceptor), Array, 'adminAuthentica...')
#25 /vendor/magento/module-backend/App/Action/Plugin/Authentication.php(143): Magento\Framework\Interception\Chain\Chain->Magento\Framework\Interception\Chain\{closure}(Object(Magento\Framework\App\Request\Http))
#26 /vendor/magento/framework/Interception/Chain/Chain.php(67): Magento\Backend\App\Action\Plugin\Authentication->aroundDispatch(Object(Magento\Theme\Controller\Adminhtml\Design\Config\Edit\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#27 /vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Theme\\C...', 'dispatch', Object(Magento\Theme\Controller\Adminhtml\Design\Config\Edit\Interceptor), Array, 'adminMassaction...')
#28 /vendor/magento/module-backend/App/Action/Plugin/MassactionKey.php(33): Magento\Theme\Controller\Adminhtml\Design\Config\Edit\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#29 /vendor/magento/framework/Interception/Interceptor.php(142): Magento\Backend\App\Action\Plugin\MassactionKey->aroundDispatch(Object(Magento\Theme\Controller\Adminhtml\Design\Config\Edit\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#30 /var/generation/Magento/Theme/Controller/Adminhtml/Design/Config/Edit/Interceptor.php(39): Magento\Theme\Controller\Adminhtml\Design\Config\Edit\Interceptor->___callPlugins('dispatch', Array, Array)
#31 /vendor/magento/framework/App/FrontController.php(55): Magento\Theme\Controller\Adminhtml\Design\Config\Edit\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#32 /vendor/magento/framework/Interception/Interceptor.php(74): Magento\Framework\App\FrontController->dispatch(Object(Magento\Framework\App\Request\Http))
#33 /vendor/magento/framework/Interception/Chain/Chain.php(70): Magento\Framework\App\FrontController\Interceptor->___callParent('dispatch', Array)
#34 /vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Framewo...', 'dispatch', Object(Magento\Framework\App\FrontController\Interceptor), Array, 'install')
#35 /vendor/magento/framework/Module/Plugin/DbStatusValidator.php(69): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#36 /vendor/magento/framework/Interception/Interceptor.php(142): Magento\Framework\Module\Plugin\DbStatusValidator->aroundDispatch(Object(Magento\Framework\App\FrontController\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#37 /var/generation/Magento/Framework/App/FrontController/Interceptor.php(26): Magento\Framework\App\FrontController\Interceptor->___callPlugins('dispatch', Array, Array)
#38 /vendor/magento/framework/App/Http.php(135): Magento\Framework\App\FrontController\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#39 /vendor/magento/framework/App/Bootstrap.php(258): Magento\Framework\App\Http->launch()
#40 /index.php(39): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http))
#41 {main}

You should add "header_christmas_theme" into existing fieldset or add new fieldset with a separate name abnd include it into the configuraion xml file

Try this. For me it worked!
remove from di.xml this
<item name="componentType" xsi:type="string">field</item>
and in design:config_form.xml add this
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<fieldset name="other_settings" sortOrder="30">
<fieldset name="header">
<field name="header_christmas_theme" formElement="select">
<settings>
<validation>
<rule name="validate-no-html-tags" xsi:type="boolean">true</rule>
</validation>
<dataType>text</dataType>
<componentType>field</componentType>
<label translate="true">Set Christmas Theme</label>
<dataScope>header_christmas_theme</dataScope>
</settings>
</field>
</fieldset>
</fieldset>

Related

magento 2 admin form ui component

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>

Flutter url_launcher Unhandled Exception: Could not launch youtube url (Caused by canLaunch)

I'm trying to use the url_launcher plugin to open youtube videos by link but the canLaunch function keeps throwing an error. I'm able to bypass this error only by completely removing the canLaunch function but can't figure out what is wrong.
Code not working:
_goToVideo(YoutubeVideoData video) async {
if (await canLaunch(video.url)) {
await launch(video.url);
} else {
throw 'Could not launch ${video.url}';
}
}
Code working:
_goToVideo(YoutubeVideoData video) async {
await launch(video.url);
}
I'm not quite sure why I can't use the canLaunch method as written in the README Example
Error:
E/flutter (12574): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Could not launch https://www.youtube.com/watch?v=-3g5WlqJtIo
E/flutter (12574): #0 _goToVideo (package:esfandapp/widgets/newsList/videoCard.dart:71:5)
E/flutter (12574): <asynchronous suspension>
E/flutter (12574): #1 VideoCard.build.<anonymous closure> (package:esfandapp/widgets/newsList/videoCard.dart:13:20)
E/flutter (12574): #2 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:992:19)
E/flutter (12574): #3 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:1098:38)
E/flutter (12574): #4 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:184:24)
E/flutter (12574): #5 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:524:11)
E/flutter (12574): #6 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:284:5)
E/flutter (12574): #7 BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:256:7)
E/flutter (12574): #8 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:158:27)
E/flutter (12574): #9 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:224:20)
E/flutter (12574): #10 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:200:22)
E/flutter (12574): #11 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:158:7)
E/flutter (12574): #12 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:104:7)
E/flutter (12574): #13 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:88:7)
E/flutter (12574): #14 _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (12574): #15 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (12574): #16 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (12574): #17 _invoke1 (dart:ui/hooks.dart:267:10)
E/flutter (12574): #18 _dispatchPointerDataPacket (dart:ui/hooks.dart:176:5)
Widget using the function:
class VideoCard extends StatelessWidget {
final YoutubeVideoData video;
VideoCard({this.video});
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () => _goToVideo(video),
child: Container(
child: Card(
child: Container(
child: Column(
children: [
Align(
child: Padding(
child: Text(
video.title,
style: TextStyle(
fontFamily: 'Roboto Condensed',
fontSize: 16,
),
),
padding: EdgeInsets.fromLTRB(15, 0, 15, 10),
),
alignment: Alignment.centerLeft,
),
Container(
child: Image.network(video.thumbnails[1], fit: BoxFit.cover,),
width: MediaQuery.of(context).size.width,
),
Align(
child: Container(
child: Text(
video.date.toString() + "",
style: TextStyle(
fontFamily: 'Roboto Condensed',
fontSize: 14,
fontWeight: FontWeight.w300,
),
),
padding: EdgeInsets.fromLTRB(15, 5, 15, 0),
),
alignment: Alignment.centerLeft,
),
],
),
width: MediaQuery.of(context).size.width - 32,
padding: EdgeInsets.symmetric(
horizontal: 0,
vertical: 10,
),
alignment: Alignment.center,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(25))),
),
),
);
}
}
Starting from API30 (Android 11), your Android app has to list all apps it interacts with.
You can add:
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
in your android manifest to bypass it or specifically list them.
For more info:
https://developer.android.com/about/versions/11/privacy/package-visibility
Personally, I don't like the uncertainty that seems to come with using the QUERY_ALL_PACKAGES permission (because Google could stop letting people use it in the future). For that reason, I did some investigation and found that adding the following to my AndroidManifest.xml allows my app to open the browser, phone app and email app on API 30:
<manifest>
<!-- Nest within the manifest element, not the application element-->
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
<intent>
<action android:name="android.intent.action.DIAL" />
<data android:scheme="tel" />
</intent>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="*/*" />
</intent>
</queries>
<application>
....
</application>
</manifest>
To get the same functionality working on iOS, it may be necessary to add the following to your info.plist file:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https</string>
<string>http</string>
<string>tel</string>
<string>mailto</string>
</array>
Just wanted to share in case it helps someone else out.
Even after trying accepted answer, If its not working for you then Please try followed code.
PRE STEPS: Do as accepted answer suggested.
Add following tags in AndroidManifest.xml before <application/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
<intent>
<action android:name="android.intent.action.DIAL" />
<data android:scheme="tel" />
</intent>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="*/*" />
</intent>
</queries>
NOW WHAT I HAVE DONE
Create one method:
Future<void> _makeSocialMediaRequest(String url) async {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
and Called it by following way:
//FOR EMAIL
final Uri _emailLaunchUri = Uri(
scheme: 'mailto',
path: 'pratik13butani#gmail.com',
queryParameters: {'subject': 'Pratik Butani'});
_makeSocialMediaRequest(_emailLaunchUri.toString());
//FOR PHONE NUMBER:
final Uri _phoneLaunchUri =
Uri(scheme: 'tel', path: postOffice.mobileNo);
_makeSocialMediaRequest(_phoneLaunchUri.toString());
//FOR ANY URL.. YOU CAN PASS DIRECT URL..
_makeSocialMediaRequest("http://pratikbutani.com");
Its working for me. Hopefully it will work for you too. Thank you.
bro only put '!' before "if (!await canLaunch(url))"
Use this -->
if (!await canLaunch(url)){
await launch(
url,
forceSafariVC: false,
forceWebView: false,
headers: <String, String>{'my_header_key': 'my_header_value'},
);
} else {
throw 'Could not launch $url';
}
For Android Use the below code in Android/main/res/AndroidManifest.xml like the showed in the image
and here is the code
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
<intent>
<action android:name="android.intent.action.DIAL" />
<data android:scheme="tel" />
</intent>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="*/*" />
</intent>
For IPhone ios/Runner/Info.plist like the showed in the image
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https</string>
<string>http</string>
<string>tel</string>
<string>mailto</string>
Make sure to add in the android manifest the below line
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
Don't forget about the Info.plist as well
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https</string>
<string>http</string>
<string>tel</string>
<string>mailto</string>
</array>
I spent nearly 2 hours to find what is wrong and after I closed the application from the recent tab and re-run the app it worked perfectly fine.
Things you might missed,
adding Url_launcher dependency in pubspec.yaml
Adding queries in Android manifest file after tag
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
</intent>
</queries>
Adding keys in the info.plist file under ios directory
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https</string>
<string>http</string>
</array>
Just try to uninstall app and run the code
if (await canLaunchUrl(Uri.parse(url))) {
await launchUrl(Uri.parse(url),
mode: LaunchMode.externalApplication, );
}
i faced same error using win and linux for android developments
and solve it with these steps
the idea is to add the to AndroidManifest.xml in app/src/main/AndroidManifest.xml
to do so and to make it work without error you must update the gardle version so here is the steps
1-updated my gradle-wrapper.properties to gradle-6.7.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
2- updated my classpath in android/build.gradle to com.android.tools.build:gradle:4.2.1
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
3- add the above to my AndroidManifest.xml in app/src/main/AndroidManifest.xml
<queries>
<!-- If your app opens https URLs -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
<!-- If your app makes calls -->
<intent>
<action android:name="android.intent.action.DIAL" />
<data android:scheme="tel" />
</intent>
<!-- If your app emails -->
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="*/*" />
</intent>
</queries>
and now everything work fine
If none of the above works, try adding this in the AndroidManifest.xml (main one if you have that). Add this code snipped just above the <application> tag.
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
</intent>
</queries>
For Android Just add in your androidmanifest.xml file
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
For iOS add these in your info.plist file
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https</string>
<string>http</string>
<string>tel</string>
<string>mailto</string>
</array>
QUERY_ALL_PACKAGES (not recommended)
Because Google could stop letting people use it in the future as mentioned in the official document
if you use launch any url from your app just use
<manifest package="com.example.game">
<queries>
<package android:name="com.android.chrome" />
</queries>
...
</manifest>
likewise you can add <queries> depends on your need.
ex.
<queries>
<!-- If your app opens https URLs -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
<!-- If your app makes calls -->
<intent>
<action android:name="android.intent.action.DIAL" />
<data android:scheme="tel" />
</intent>
<!-- If your app emails -->
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="*/*" />
</intent>
</queries>
This worked for me
if (!url.contains('http')) url = 'https://$url';
Complete Method:
launchURL(String url) async {
if (!url.contains('http')) url = 'https://$url';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}

Magento 2 UiComponent form with tabs has empty fields

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;
}

In Magento2 (2.2.5) uicomponent form in frontend, SAVE button not appearing with form

I added uiform in frontend. Form is loading but save button is not appearing. Code details:
1. employee_form.xml code:
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">employee_form.employee_form_data_source</item>
</item>
<item name="label" xsi:type="string" translate="true">Assign Product Form</item>
<item name="template" xsi:type="string">templates/form/collapsible</item>
<item name="spinner" xsi:type="string">uiform_index_columns2</item>
</argument>
<settings>
<buttons>
<button name="save" class="Cn\Uiform\Block\Employee\Form\SaveButton"/>
<button name="back">
<url path="*/*/"/>
<class>back</class>
<label translate="true">Back</label>
</button>
</buttons>
<namespace>employee_form</namespace>
<dataScope>data</dataScope>
<deps>
<dep>employee_form.employee_form_data_source</dep>
</deps>
</settings>
<dataSource name="employee_form_data_source">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
</item>
</argument>
<settings>
<submitUrl path="*/*/save"/>
</settings>
<dataProvider class="Cn\Uiform\Model\DataProvider" name="employee_form_data_source">
<settings>
<primaryFieldName>id</primaryFieldName>
<requestFieldName>id</requestFieldName>
</settings>
</dataProvider>
</dataSource>
2. DataProvide.php methods code
public function prepareMeta(array $meta) {
return $meta;
}
public function getData() {
return [];
}
3. SaveButton.php class code
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
class SaveButton extends GenericButton implements ButtonProviderInterface {
public function getButtonData() {
return [
'label' => __('Save Slide'),
'class' => 'save primary',
'data_attribute' => [
'mage-init' => ['button' => ['event' => 'save']],
'form-role' => 'save',
],
'sort_order' => 90,
];
}
}
4. di.xml
<!--for edit uiform-->
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
<arguments>
<argument name="collections" xsi:type="array">
<item name="employee_form_data_source" xsi:type="string">Cn\Uiform\Model\ResourceModel\Employee\Collection</item>
</argument>
</arguments>
</type>
=> But, the ui form is loading without SAVE button.
For displaying buttons on frontend UI component form. You have to add a Container reference in your layout.
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="page.main.actions">
<block class="Magento\Framework\View\Element\Template" name="page.actions.toolbar" template="Magento_Backend::pageactions.phtml"/>
</referenceContainer>
<referenceContainer name="admin.scope.col.wrap" htmlClass="admin__old" />
<referenceContainer name="content">
<uiComponent name="employee_form"/>
</referenceContainer>
</body>
</page>
I've never implemented IU components on the frontend, but as far as the backend goes, my own forms have the buttons included inside the 'data' argument. E.g.
<argument name="data" xsi:type="array">
<item name="buttons" xsi:type="array”>
<item name="save" xsi:type="string">Cn\Uiform\Block\Employee\Form\SaveButton</item>
</item>
</argument>

Adding a new input form to checkout in magento 2

Want to add an input form to checkout page for updating the shipping price. So far, I have done the following modifications :
1) Created /view/frontend/web/js/custom-checkout-form.js file and added the following code:
define(
[
'ko',
'uiComponent',
'underscore',
'Magento_Checkout/js/model/step-navigator'
],
function (
ko,
Component,
_,
stepNavigator
) {
'use strict';
/**
*
* mystep - is the name of the component's .html template,
* your_module_dir - is the name of the your module directory.
*
*/
return Component.extend({
defaults: {
template: 'your_module_dir/mystep'
},
//add here your logic to display step,
isVisible: ko.observable(true),
/**
*
* #returns {*}
*/
initialize: function () {
this._super();
// register your step
stepNavigator.registerStep(
//step code will be used as step content id in the component template
'step_code',
//step alias
null,
//step title value
'Step Title',
//observable property with logic when display step or hide step
this.isVisible,
_.bind(this.navigate, this),
/**
* sort order value
* 'sort order value' < 10: step displays before shipping step;
* 10 < 'sort order value' < 20 : step displays between shipping and payment step
* 'sort order value' > 20 : step displays after payment step
*/
15
);
return this;
},
/**
* The navigate() method is responsible for navigation between checkout step
* during checkout. You can add custom logic, for example some conditions
* for switching to your custom step
*/
navigate: function () {
},
/**
* #returns void
*/
navigateToNextStep: function () {
stepNavigator.next();
}
});
}
);
2) Created the HTML template /view/frontend/web/template/custom-checkout-form.html
<div>
<form id="custom-checkout-form" class="form" data-bind="attr: {'data-hasrequired': $t('* Required Fields')}">
<fieldset class="fieldset">
<legend data-bind="i18n: 'Custom Checkout Form'"></legend>
<!-- ko foreach: getRegion('custom-checkout-form-fields') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</fieldset>
<button type="reset">
<span data-bind="i18n: 'Reset'"></span>
</button>
<button type="button" data-bind="click: onSubmit" class="action">
<span data-bind="i18n: 'Submit'"></span>
</button>
</form>
</div>
3) Deleted all files in the pub/static/frontend and var/view_preprocessing directories. Reloaded the pages.
4) Created a checkout_index_index.xml layout update in the /view/frontend/layout/
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shipping-step" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shippingAddress" xsi:type="array">
<item name="children" xsi:type="array">
<item name="before-form" xsi:type="array">
<item name="children" xsi:type="array">
<!-- Your form declaration here -->
<item name="custom-checkout-form-container" xsi:type="array">
<item name="component" xsi:type="string">%your_module_dir%/js/view/custom-checkout-form</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="config" xsi:type="array">
<item name="template" xsi:type="string">%your_module_dir%/custom-checkout-form</item>
</item>
<item name="children" xsi:type="array">
<item name="custom-checkout-form-fieldset" xsi:type="array">
<!-- uiComponent is used as a wrapper for form fields (its template will render all children as a list) -->
<item name="component" xsi:type="string">uiComponent</item>
<!-- the following display area is used in template (see below) -->
<item name="displayArea" xsi:type="string">custom-checkout-form-fields</item>
<item name="children" xsi:type="array">
<item name="text_field" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</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/input</item>
</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="dataScope" xsi:type="string">customCheckoutForm.text_field</item>
<item name="label" xsi:type="string">Text Field</item>
<item name="sortOrder" xsi:type="string">1</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="string">true</item>
</item>
</item>
<item name="checkbox_field" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/element/boolean</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/checkbox</item>
</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="dataScope" xsi:type="string">customCheckoutForm.checkbox_field</item>
<item name="label" xsi:type="string">Checkbox Field</item>
<item name="sortOrder" xsi:type="string">3</item>
</item>
<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">Value 1</item>
<item name="value" xsi:type="string">value_1</item>
</item>
<item name="2" xsi:type="array">
<item name="label" xsi:type="string">Value 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>
<item name="date_field" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/element/date</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/date</item>
</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="dataScope" xsi:type="string">customCheckoutForm.date_field</item>
<item name="label" xsi:type="string">Date Field</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="string">true</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
But it is not working for me. Referred the magento's doc http://devdocs.magento.com/guides/v2.0/howdoi/checkout/checkout_form.html. Correct me if I'm doing wrong in naming of the files or so. I would really appreciate if someone could help!!!