Dart / Flutter - Validating a string for URL - string

I'm trying to create a system in which I can validate a string to check if it's a url or not. (https://www.google.com/)
I found the flutter package validator but this isn't dart 2 compatible, so won't be compatible with my code.
Similarly named, I also found the validators package but I can't seem to get it working correctly with my code, as it throws the following error; (hope you like my project name ;)
Because every version of flutter_test from sdk depends on test 1.3.0
and every version of validators depends on test ^1.3.3, flutter_test from sdk is incompatible with validators.
So, because gucci depends on both validators ^1.0.0+1 and flutter_test any from sdk, version solving failed.
Unable to reload your application because "flutter packages get" failed to update package dependencies.
Exception: pub get failed (1)
If you could either find a fix for validators so that it doesn't throw this error and thus works correctly with my code, or suggest another method of validating a string to be URL compliant that would be great.
Thanks
Edit - My pubspec.yaml file
name: gucci
description: A new Flutter project.
dependencies:
flutter:
sdk: flutter
cupertino_icons:
barcode_scan:
gradient_app_bar:
url_launcher:
validate: ^1.7.0
dev_dependencies:
flutter_test:
sdk: flutter
fonts:
- family: PlayfairDisplay
fonts:
- asset: fonts/PlayfairDisplay-BoldItalic.ttf
- family: Kanit
fonts:
- asset: fonts/Kanit-ExtraBoldItalic.ttf
- family: Poppins
fonts:
- asset: fonts/Poppins-BoldItalic.ttf
- family: PoppinsLightItalic
fonts:
- asset: fonts/Poppins-LightItalic.ttf
- family: PoppinsMediumItalic
fonts:
- asset: fonts/Poppins-MediumItalic.ttf

To check Valid URL string you just have to use Uri.parse() like below.
bool _validURL = Uri.parse(_adVertData.webLink).isAbsolute;
Just check value of _validURL

Uri.tryParse(mystring)?.hasAbsolutePath ?? false;
Some example results:
url
result
'https://stackoverflow.com/questions/52975739/dart-flutter-validating-a-string-for-url'
true
asd
false
asd:asd
false
%EMPTY_STRING%
false
google.nl
false
https:
false
https://
false
https://a
false
https://a/
true

var urlPattern = r"(https?|http)://([-A-Z0-9.]+)(/[-A-Z0-9+&##/%=~_|!:,.;]*)?(\?[A-Z0-9+&##/%=~_|!:‌​,.;]*)?";
var match = new RegExp(urlPattern, caseSensitive: false).firstMatch('https://www.google.com');
You can use RegExp too.

I used the following method below. Depending on your rec, all valid URLs need to have a host (ex, google.com). If a URL does not have a host it returns an empty string (not undefined or null).
bool isURLValid = Uri.parse('https://google.com/').host.isNotEmpty;
Using .isAbsolute, as some have already reported, marks URLs such as 'http:' to be valid URLs which not.

For some reason, the validators package is requiring a pretty recent version of flutter's testing library rather than leaving it up to the application. Maybe there's a good reason for that (i.e. they're using a new feature).
The flutter engine internally requires a particular version of the flutter_test library (which is why it's generally a bad idea to specify a version of it). So to fix this you'll have to upgrade your flutter by running flutter upgrade. If you're already at the most recent version of the channel you're in, you may have to run flutter channel dev or flutter channel master to switch to a channel (branch really) that's updated more often.
I run on the dev branch/channel for the most part and while it very occasionally has problems, it doesn't happen a lot. I'd advise against using the master branch if possible though.

Validation using RegEx
String hasValidUrl(String value) {
String pattern = r'(http|https)://[\w-]+(\.[\w-]+)+([\w.,#?^=%&:/~+#-]*[\w#?^=%&/~+#-])?';
RegExp regExp = new RegExp(pattern);
if (value.length == 0) {
return 'Please enter url';
}
else if (!regExp.hasMatch(value)) {
return 'Please enter valid url';
}
return null;
}
Validation using in-built package
final Uri uri = Uri.tryParse(value);
if (!uri.hasAbsolutePath) {
return 'Please enter valid url';
}
If you want some special case like you have to validate deepLink then RegEx practice is best.

For RegExp, if you are going to find URL in a string, you can use this one.
r'^((?:.|\n)*?)((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)([-A-Z0-9.]+)(/[-A-Z0-9+&##/%=~_|!:,.;]*)?(\?[A-Z0-9+&##/%=~_|!:‌​,.;]*)?)'
It can be used when you are highlighting URL in a string. For example in a chat app, you can highlight URL in a sent chat message.
This validates google.com, https://google.com, http://google.com all.

I'm using this way to validate Urls. In your TextFormField's use this validator. here your url should be start from www.
validator: (website) {
String pattern =
r'^((?:.|\n)*?)((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)([-A-Z0-9.]+)(/[-A-Z0-9+&##/%=~_|!:,.;]*)?(\?[A-Z0-9+&##/%=~_|!:‌​,.;]*)?)';
RegExp regExp = RegExp(pattern);
if (website.isEmpty) {
return "Please enter your website";
} else if (!(regExp.hasMatch(website))) {
return "Website Url must be started from www";
} else {
return null;
}
},

TextEditingController urlController = TextEditingController();
String urlData = '';
static final GlobalKey<FormFieldState<String>> _orderFromkey =
GlobalKey<FormFieldState<String>>();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: [
appBar(label: appName),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
key: _orderFromkey,
controller: urlController,
validator: (value) {
String patttern = r"((https?:www\.)|(https?:\/\/)|(www\.))[-a-zA-Z0-9#:%._\+~#=]{1,256}\.[a-zA-Z0-9]{1,6}(\/[-a-zA-Z0-9()#:%_\+.~#?&\/=]*)?";
RegExp regExp = new RegExp(patttern);
if (!regExp.hasMatch(value!)) {
return 'Please enter valid URL';
}
},
decoration: InputDecoration(
fillColor: appColor,
labelText: "url",
labelStyle: new TextStyle(color: appColor),
contentPadding: EdgeInsets.only(left: 10, right: 10),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: appColor),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: black),
),
hintText: 'Enter Your URL'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
print('_orderFromkey: ${_orderFromkey}');
final FormFieldState<String>? form =
_orderFromkey.currentState;
if (form!.validate()) {
urlData = urlController.text;
Get.toNamed('/showQr', arguments: urlData);
print('text : ${urlData}');
} else {
// _autoValidation = true;
}
},
child: Container(
width: ScreenSize.size.width * 0.6,
height: ScreenSize.size.height * 0.1,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: appColor,
),
child: const Align(
alignment: Alignment.center,
child: Text(
'Submit',
style: TextStyle(
fontSize: 20,
color: white,
fontWeight: FontWeight.w700),
textAlign: TextAlign.center,
)),
),
),
),
],
)),
);
}

You can use the url_launcher package for this.
Future<bool> checkIfUrlIsValid({required String url}) async {
if (await canLaunchUrl(Uri.parse(url))) {
return true;
}
return false;}
checkIfUrlIsValid(url: 'https://google.com'); // true;
checkIfUrlIsValid(url: 'google com'); // false;

Use this simple function then you can identify string is valid URL or not
bool isURl(String url){
return RegExp(r'^((?:.|\n)*?)((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)([-A-Z0-9.]+)(/[-A-Z0-9+&##/%=~_|!:,.;]*)?(\?[A-Z0-9+&##/%=~_|!:‌​,.;]*)?)')
.hasMatch(url); }

Related

type 'String' is not a subtype of type 'List<String>' in type cast?

How can I fix that? I can't run the code because there is an error at String
Text(
questions[_questionsIndex]['questionText'] as String,
style: TextStyle(color: Colors.orange, fontSize: 30),
),
...(questions[_questionsIndex]['questionText'] as List<String>).map((answer) {
return Answer(_answerQuestions, answer);
}).toList()
The problem is this:
questions[_questionsIndex]['questionText'] as String
questions[_questionsIndex]['questionText'] as List<String>
How can questions[_questionsIndex]['questionText'] be a String and a List<String> at the same time?
I can't know for sure since you didn't show whats inside of questions variable and we don't know what you want to do but you probably want to do something like this:
...(questions as List<Map<String, dynamic>>).map((question) {
return Answer(_answerQuestions, question['questionText']);
}).toList()
I decided to do an online course at Udemy (flutter) and this code was shown, to load the questions & answers by a quiz:
Question(
questions[_questionsIndex]['questionText'],
),
...(questions[_questionsIndex]['questionText'] as List<String>).map((answer) {
return Answer(_answerQuestions, answer);
}).toList()
but actually it doesn't work. I tried to put 'as String' to the first Line, but the Emulator does show an error. So I tried your Version but it doesn't helped me

Unhandled Exception: type 'List<String>' is not a subtype of type 'String' in type cast - FLUTTER

This icon button, once pressed, opens a howOkCancelAlertDialog and if you click on ok, a showTextInputDialog opens, assigning the input entered from the keyboard to the input variable which is of the List type.
IconButton( icon: const Icon(FeatherIcons.arrowRight, color: Colors.black,),
onPressed: () async {
final result = await
showOkCancelAlertDialog(
context: context,
title: 'Change or Create a new Password',
message:
'This will remove your existing Password or create a new one',
);
if (result == OkCancelResult.ok) {
final input = await showTextInputDialog(
textFields: [DialogTextField(keyboardType: TextInputType.numberWithOptions(decimal: true),
),
],
context: context,
title: 'Change or Create a new Password',
message: 'enter your new password',
);
print ("PROVAA PRIMA DELL IF"+input.toString());
context.read<SettingsBloc>().changePassword(input as String);
SettingsPage.inputPassword = input as String;
SettingsPage.inputPassword = tec.text;
setState(() {
encryptedText = encryptAES(SettingsPage.inputPassword);
print("PROVA ENCRYPTED TEXT "+encryptedText);
});
prefs.setString('savedPass', encryptedText);
encryptedText = decryptAES(encryptedText);
print("PROVA TESTO DECRIPTATO " + encryptedText);
}
},
),
In execution, however, I get this error because this variable of type List cannot be assigned to variables of type String. Can you help me solve this problem and make sure that I can assign the input without getting any kind of problem in execution?
As per the showTextInputDialog documentation, it's clear that it returns List.
You can't convert that to String using:
input as String
You need to access the values through index, in your case you can use:
input.first as String

Flutter slider with web

I am trying to build music player app which has slider, my current slider code shown below works fine with Mobile device but it doesn't work on Flutter web, it seems like flutter slider doesn't support slider on web yet. I tried finding out alternative packages but none of them seems to support web. Is there any customized version which we can use for web?
Widget slider() {
return Slider(
activeColor: Colors.white10,
inactiveColor: AppColors.red200,
label: inuseAudioinfo.duration.inSeconds.toString(),
min: 0.0,
max: (inuseAudioinfo.position.inSeconds ?? 0.0).toDouble(),
value: (getSleepkerPosition(inuseAudioinfo.position.inSeconds,
inuseAudioinfo.duration.inSeconds))
.toDouble(),
divisions: 9,
onChangeStart: (double value) {
print('Start value is ' + value.toString());
},
onChangeEnd: (double value) {
print('Finish value is ' + value.toString());
},
onChanged: (double value) {
setState(() {
if (value == inuseAudioinfo.position.inSeconds) {
} else {
seekToSecond(value.toInt());
value = value;
}
});
});
}
I was using https://pub.dev/packages/audioplayers plugin to get position and duration, it seems like this plugin doesn't support web yet. I replaced my code with https://pub.dev/packages/assets_audio_player and it worked.

Is there a way to stop CustomScrollView from automatically scrolling down when Keyboard is activated?

It seems that whenever I focus on a TextField (that sits inside a SliverPersistentHeader) SliverList+SliverPersistentHeader scrolls down. I have created some mockups of what I mean below:
So in this mockup, the user starts off at the first layout, scrolls up to continue viewing the lsit and then when they click on the TextField, the whole thing shifts down. Any way to stop that?
I have also attached my basic Scaffold code for your perusal:
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Consts.coMainBackground,
resizeToAvoidBottomInset: false,
body: CustomScrollView(
slivers: <Widget>[
_sliverAppBar(),
_makeHeader(),
BlocBuilder<AllPersonsBloc, AllPersonsState>(
builder: (context, state) {
if (state is AllPersonsLoading) {
return _buildLoading();
} else if (state is AllPersonsLoaded) {
return _sliverList(context, state.persons);
} else if (state is AllPersonsError) {
return _buildErrorMessage(state.message);
} else {
return _buildErrorMessage('Unknown error!');
}
},
),
],
),
);
}
the _makeHeader creates the SliverPersistentHeader and the rest I think should make sense based on names.
Your help would greatly appreciated :)
Thanks!
Got it...
return SliverAppBar(
automaticallyImplyLeading: false,
backgroundColor: Consts.coForestGreenBackground,
expandedHeight: 207,
titleSpacing: 0,
elevation: 0,
floating: false,
pinned: false,
snap: false,
flexibleSpace: FlexibleSpaceBar(
Note that the item is not pinned/floated/snapped. Then its important that the input (TextField in this case) has a scrollPadding (top) of 0.
Your scaffold will ALSO need an appbar. So technically you have an appbar and a SliverAppBar but the SliverAppBar is just to wrap the flexibleSpace.
Or rather, zero after any padding on the element it self. In my case its 40 since the TextField has a top padding of 30 and another 10 from the element that contains it etc.

How to write condition statements in flutter?

I wanted to learn how can I apply "if" condition in my flutter code? As I am new to dart language coding.
Suppose in a code like below, i want to add condition that if the counter's value is 1 then "You have pushed the button $_counter time" else "You have pushed the button $_counter times"
children: <Widget>[
new Text(
'You have pushed the button $_counter times:',
)/*,
new Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),*/
]
P.S. its just a simple example for me to understand how to use if condition in flutter.
For such simple cases you can use the ternary if ?: inside string interpolation:
new Text(
'You have pushed the button $_counter time${_counter != 1 ? 's' : ''}:',
)
for the case of the conditions you have just a single condition then you can use the basic ternary operators,
child: Text(
'{fee=="FREE"?"Free":fee}',
),
But if you have multiple conditions or value that need to compare from the index position(i.e. you have to fetch value and then need to put in condition) in listview then you can add method as your text value in your Widget as follows:
child: Text(
'${checkForPrice(index)}',
),
),
checkForPrice(int index) {
String strFee = data['payload']['webinar'][index]['fee'];
String finalFee = "";
if (strFee == "FREE") {
finalFee = 'FREE';
} else {
finalFee = '\$ ${data['payload']['webinar'][index]['fee']}';
}
return finalFee;}
This will definitely help you in showing data with multiple conditions.
at the first time i tried flutter i have no idea what dart language is but after some browsing i found this useful documentation. You can find anything you looking for right there including if statement that you are asking about. But i can tell you the if statement works the same as any other language such as JavaScript, Java, etc.
Edit: here i give you some example how to use it in flutter
Future<Null> toTheHomeScreen() async {
await _signInWithGoogle();
SharedPreferences sprefs = await SharedPreferences.getInstance();
if (sprefs.getString('idToken').isNotEmpty) {
new Future.delayed(new Duration(seconds: 3), () {
new CircularProgressIndicator();
Navigator.of(context).push(
new MaterialPageRoute(
builder: (BuildContext context) {
return new HomeScreen();
}
)
);
});
} else {
Navigator.of(context).pop();
}
}
the if statement check if there is any key named 'idToken' stored in sharedpref, if it not empty user will redirect to home page.
I hope this will help you.

Resources