Understanding flutter syntax - dart

I'm reviewing someones flutter code, and there is some code in there i don't understand what its doing.
I don't understand some of the syntax since in never seen it in any other language.
Here are three examples...
1. final Geolocator geolocator = Geolocator()
..forceAndroidLocationManager = true;
2. final firstName = appState?.user?.firstName ?? '';
3. var envelope = new Envelope()
..from = 'support#example.com'
..recipients.add(Globals.sosEmail)
..ccRecipients.add(email)
..subject = '$firstName $lastName hello. ${new DateTime.now()}'
..text = "Hello"'
..html ='<p>Hey!</p>';
What is (2) doing? What does ?. and ?? '' mean?
There is syntax where there is two dots in a row like in (1) ..forceAndroidLocationManager, or ..from, ..text etc.
Anybody knows what the above 3 examples of code does?
Thanks!

The first example is cascade notation
This means that you can make several operations on the same object. Example from the dart website:
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
The second example is about null-aware operators
final firstName = appState?.user?.firstName ?? '';
What's happening here is that we have a variable called appState and appState?.user means that we're only supposed to try to access user if appState is not null (so we don't get a nullpointer error. Same goes for user?.firstname.
Finally, ?? means 'set 'firstName' to appState.user.firstName if it's not null, otherwise set it to ''.
The third example is the same thing as the first.

Related

Chaining method calls

According to official Dart documentation, it is mentioned that:
Chaining method calls
a..b = true..c = 5;
Cascade used for chaining access to methods and other members.
Equivalent:
a.b = true; a.c = 5;
Can someone explain the meaning of the above lines?
Consider user as an instace of following class:
class User {
int age;
String firstName;
String lastName;
}
Now you can update data in user as following:
user.age = 5;
user.firstName = 'John';
user.lastName = 'Doe';
but if you use chaining access as described in the documentation.
Then it will look something like this:
user..age = 5
..firstName = 'John'
..lastName = 'Doe';
Note: sequence of assignment of the properties does not matter, but it might be of importance while calling functions or methods like this.
Just a simple & random example:
painter..computeLayout()
..initializePaint()
..render();
above is same as:
painter.computeLayout();
painter.initializePaint();
painter.render();
in the above example all of the methods were called on painter object/instance but the sequence here must be followed as without paint or layout the render will not work.
Cascades
To perform a sequence of operations on the same object, use cascades (..). We’ve all seen an expression like this:
myObject.someMethod()
It invokes someMethod() on myObject, and the result of the expression is the return value of someMethod().
Here’s the same expression with a cascade:
myObject..someMethod()
Although it still invokes someMethod() on myObject, the result of the expression isn’t the return value — it’s a reference to myObject! Using cascades, you can chain together operations that would otherwise require separate statements. For example, consider this code:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
With cascades, the code becomes much shorter, and you don’t need the button variable:
querySelector('#confirm')
..text = 'Confirm'
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));

Unable to use SaveAndPublish from ContentService

I'm trying to save my IContent called child, but on this line(contentService.SaveAndPublish(child);) I get the following error: Object reference not set to an instance of an object.
if (child.HasProperty("navn"))
{
child.SetValue("navn", worker.Name.ToString(), "da-dk");
}
contentService.SaveAndPublish(child);
This is how I define my contentService:IContentService contentService = Umbraco.Core.Composing.Current.Services.ContentService;
And I'm finding the children like this:
long totalChildren;
IEnumerable<IContent> children = contentService.GetPagedChildren(filialsParent.Id, 0, 100, out totalChildren);
´
Can someone point out what is wrong here?
I found out that if I do this then it works.
var umbf = Umbraco.Web.Composing.Current.Factory.GetInstance<IUmbracoContextFactory>();
using (var contextf = umbf.EnsureUmbracoContext())
{
var umbcontext = contextf.UmbracoContext;
IContentService cs = Umbraco.Core.Composing.Current.Services.ContentService;
cs.SaveAndPublish(child);
}
I believe you're getting your ContentService the wrong way and therefore it may be empty, causing a null reference exception.
If you're in a SurfaceController, you can get ContentService like this:
var cs = Services.ContentService;
If you're in a class where Services is not exposed, you can get it like this:
var cs = ApplicationContext.Current.Services.ContentService;
Read more about it in Umbracos documentation below :)
https://our.umbraco.com/documentation/Reference/Management/Services/ContentService/
Look that link, seems that Umbraco 'Save' works even if something is null but not completely:
Save is working but not completely, it is saving the content to the db
but not to the Umbraco backoffice. And even when I try wrapping the
setValues inside a
if (blogNode.HasProperty("title")) {
I still get a null reference
error.
In the OP case he's taking the wrong contentService in the first step, so i think #Mikkel answer is not completely wrong:
Turns out I had used the wrong parentId in this line:
var newBlog = contentService.CreateContent(post.Title, 1053, "umbNewsItem", 0);
the correct statement was:
var newBlog = contentService.CreateContent(post.Title, 1061, "umbNewsItem", 0);
L-

Passing query parameters in Dapper using OleDb

This query produces an error No value given for one or more required parameters:
using (var conn = new OleDbConnection("Provider=..."))
{
conn.Open();
var result = conn.Query(
"select code, name from mytable where id = ? order by name",
new { id = 1 });
}
If I change the query string to: ... where id = #id ..., I will get an error: Must declare the scalar variable "#id".
How do I construct the query string and how do I pass the parameter?
The following should work:
var result = conn.Query(
"select code, name from mytable where id = ?id? order by name",
new { id = 1 });
Important: see newer answer
In the current build, the answer to that would be "no", for two reasons:
the code attempts to filter unused parameters - and is currently removing all of them because it can't find anything like #id, :id or ?id in the sql
the code for adding values from types uses an arbitrary (well, ok: alphabetical) order for the parameters (because reflection does not make any guarantees about the order of members), making positional anonymous arguments unstable
The good news is that both of these are fixable
we can make the filtering behaviour conditional
we can detect the category of types that has a constructor that matches all the property names, and use the constructor argument positions to determine the synthetic order of the properties - anonymous types fall into this category
Making those changes to my local clone, the following now passes:
// see https://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
using (var conn = new System.Data.OleDb.OleDbConnection(
Program.OleDbConnectionString))
{
var row = conn.Query("select Id = ?, Age = ?", new DynamicParameters(
new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
) { RemoveUnused = false } ).Single();
int age = row.Age;
int id = row.Id;
age.IsEqualTo(23);
id.IsEqualTo(12);
}
}
Note that I'm currently using DynamicParameters here to avoid adding even more overloads to Query / Query<T> - because this would need to be added to a considerable number of methods. Adding it to DynamicParameters solves it in one place.
I'm open to feedback before I push this - does that look usable to you?
Edit: with the addition of a funky smellsLikeOleDb (no, not a joke), we can now do this even more directly:
// see https://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
using (var conn = new System.Data.OleDb.OleDbConnection(
Program.OleDbConnectionString))
{
var row = conn.Query("select Id = ?, Age = ?",
new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
).Single();
int age = row.Age;
int id = row.Id;
age.IsEqualTo(23);
id.IsEqualTo(12);
}
}
I've trialing use of Dapper within my software product which is using odbc connections (at the moment). However one day I intend to move away from odbc and use a different pattern for supporting different RDBMS products. However, my problem with solution implementation is 2 fold:
I want to write SQL code with parameters that conform to different back-ends, and so I want to be writing named parameters in my SQL now so that I don't have go back and re-do it later.
I don't want to rely on getting the order of my properties in line with my ?. This is bad. So my suggestion is to please add support for Named Parameters for odbc.
In the mean time I have hacked together a solution that allows me to do this with Dapper. Essentially I have a routine that replaces the named parameters with ? and also rebuilds the parameter object making sure the parameters are in the correct order.
However looking at the Dapper code, I can see that I've repeated some of what dapper is doing anyway, effectively it each parameter value is now visited once more than what would be necessary. This becomes more of an issue for bulk updates/inserts.
But at least it seems to work for me o.k...
I borrowed a bit of code from here to form part of my solution...
The ? for parameters was part of the solution for me, but it only works with integers, like ID. It still fails for strings because the parameter length isn't specifed.
OdbcException: ERROR [HY104] [Microsoft][ODBC Microsoft Access Driver]Invalid precision value
System.Data.Odbc. OdbcParameter.Bind(OdbcStatementHandle hstmt,
OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance)
System.Data.Odbc.OdbcParameterCollection.Bind(OdbcCommand command, CMDWrapper cmdWrapper, CNativeBuffer parameterBuffer)
System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader, object[] methodArguments, SQL_API odbcApiMethod)
System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader)
System.Data.Common.DbCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
Dapper.SqlMapper.QueryAsync(IDbConnection cnn, Type effectiveType, CommandDefinition command) in SqlMapper.Async.cs
WebAPI.DataAccess.CustomerRepository.GetByState(string state) in Repository.cs
var result = await conn.QueryAsync(sQuery, new { State = state });
WebAPI.Controllers.CustomerController.GetByState(string state) in CustomerController .cs
return await _customerRepo.GetByState(state);
For Dapper to pass string parameters to ODBC I had to specify the length.
var result = await conn.QueryAsync<Customer>(sQuery, new { State = new DbString { Value = state, IsFixedLength = true, Length = 4} });

How do I listen for custom events in Dart?

I want to do something like
// WARNING: this code does not work, it's illustrative
query("#myBtn").onClick.listen((e) {
window.fire["foo"];
});
window.on["foo"].listen((e) => print("foo was here"));
window.on["foo"].listen((e) => print("and here"));
Is it possible? How? I've been searching on Google for a few hours now, but I'm kind of new to programming in general, so I don't really know any keywords for this sort of thing.
Thanks! :)
-- EDIT: Solved --
Here's how to pass arguments along (The editor will complain, but it works)
List<String> myData = ["one","two"];
query("#myBtn").onClick.listen((e) {
window.on["foo"].dispatch(new CustomEvent("foo", canBubble: false, cancelable: false, detail: myData));
});
window.on["foo"].add((e) => print( e.detail[1] ));
:-)
You said you wanted to pass around data. Let's assume we have this class:
class Person {
String name;
int age;
}
then this listener:
window.on['foo'].listen((e) {
Person p = e.detail;
print(p.name); // Jack
});
All we need to pass data around is to write something like:
var p = new Person()
..name = 'Jack'
..age = 25;
var e = new CustomEvent('foo', detail: p);
window.on['foo'].dispatch(e);
This is the way to do it. See the documentation:
http://api.dartlang.org/docs/releases/latest/dart_html/Events.html
http://api.dartlang.org/docs/releases/latest/dart_html/CustomEvent.html
This should work:
window.on['foo'].listen((e) => print("foo was here"));
See the docs:
http://api.dartlang.org/docs/releases/latest/dart_html/Events.html

help with oauthService and linkedin

I am trying to iterate over a list of parameters, in a grails controller. when I have a list, longer than one element, like this:
[D4L2DYJlSw, 8OXQWKDDvX]
the following code works fine:
def recipientId = params.email
recipientId.each { test->
System.print(test + "\n")
}
The output being:
A4L2DYJlSw
8OXQWKDDvX
But, if the list only has one item, the output is not the only item, but each letter in the list. for example, if my params list is :
A4L2DYJlSwD
using the same code as above, the output becomes:
A
4
L
2
D
Y
J
l
S
w
can anyone tell me what's going on and what I am doing wrong?
thanks
jason
I run at the same problem a while ago! My solution for that it was
def gameId = params.gameId
def selectedGameList = gameId.class.isArray() ? Game.getAll(gameId as List) : Game.get(gameId);
because in my case I was getting 1 or more game Ids as parameters!
What you can do is the same:
def recipientId = params.email
if(recipientId.class.isArray()){
// smtg
}else{
// smtg
}
Because what is happening here is, as soon as you call '.each' groovy transform that object in a list! and 'String AS LIST' in groovy means char_array of that string!
My guess would be (from what I've seen with groovy elsewhere) is that it is trying to figure out what the type for recipientId should be since you haven't given it one (and it's thus dynamic).
In your first example, groovy decided what got passed to the .each{} closure was a List<String>. The second example, as there is only one String, groovy decides the type should be String and .each{} knows how to iterate over a String too - it just converts it to a char[].
You could simply make recipientId a List<String> I think in this case.
You can also try like this:
def recipientId = params.email instanceof List ? params.email : [params.email]
recipientId.each { test-> System.print(test + "\n") }
It will handle both the cases ..
Grails provides a built-in way to guarantee that a specific parameter is a list, even when only one was submitted. This is actually the preferred way to get a list of items when the number of items may be 0, 1, or more:
def recipientId = params.list("email")
recipientId.each { test->
System.print(test + "\n")
}
The params object will wrap a single item as a list, or return the list if there is more than one.

Resources