Example:
Class User {
String name;
String age;
String hobby;
User({this.name, this.age, this.hobby});
}
If I use user.name, I will get the name value, but how do I get the name of 'name' parameter? I saw this is possible in some other languages like C# and Javascript, but can't find it for Dart.
Related
I know i can create a private property by prefixing its name with an underscore (_).
but if I put the class and the main function in the same file I can access to private properties
class User {
late String email;
late String _password;
User({required String email, required String password})
: email = email,
_password = password;
}
void main() {
User u = User(email: 'myemail#gmail.com', password: 'mypassword');
print(u._password); // I can access to this private property
}
if I move the User class to a separate file everything works like expected, and i can't access private properties
import 'user.dart';
void main() {
User u = User(email: 'myemail#gmail.com', password: 'mypassword');
print(u._password); // I can't access to this private property
}
I didn't understand the reason.
Unlike Java, Dart doesn’t have the keywords public, protected, and private. If an identifier starts with an underscore (_), it's private to its library.
https://dart.dev/guides/language/language-tour#important-concepts.
So basically the underscore does not make "variable private" the way we are used to (from languages like Java or C#) but it makes private to the library (which, roughly saying, is the same as a Java package).
That's why if you put the directive part of 'main.dart'; in the user.dart and the directive part 'user.dart'; in the main.dart file you will be able to access the private field, even the class being in a different file. The part of and part directives makes two files the same library.
If you are curious why Dart uses underscores instead of access modifier keywords like public or private, see SDK issue #33383 https://github.com/dart-lang/sdk/issues/33383.
In a nutshell, from what I have understood: since the Dart language supports dynamic member access, it's far more performant use library level visibility than class-based visibility, as #eernstg said:
I think it's important to note that this is actually not about syntax. You could choose lots of different syntactic forms for the same thing, but it's the underlying structure that matters.
If you want to access a variable from a class, use this
class User {
late String email;
late String _password;
User({required String email, required String password})
: email = email,
_password = password;
//this is called a get function, which you can call from class instance.
String get getUserPassword => _password;
}
import 'user.dart';
void main() {
User u = User(email: 'myemail#gmail.com', password: 'mypassword');
print(u.getUserPassword); // changes here
}
Happy coding!!
Email( List<String> to, String from, {String subject:null, String message:null, DateTime datetime:null, HashMap<String, List<String>> meta:null, List<Attachment> attachments:null})
get this error:
Uncaught NoSuchMethodError: incorrect number of arguments passed to method named ''
Receiver: ""
Tried calling: (Instance of 'JSArray<String>', "will#fallenreaper.com", Instance of '_HashMap<String, Object>')
Found: (to, from, subject, message, datetime, meta, attachments)
My class is:
class Email{
Email( List<String> to, String from, {String subject:null, String message:null, DateTime datetime:null, HashMap<String, List<String>> meta:null, List<Attachment> attachments:null}){
//do stuff.
}
}
im trying to make it such that to and from are required, but the rest are optionally going to be passed in, in a map. I thought i was doing this right, but it doesnt seem to be correct.
The DartPad is at: https://dartpad.dartlang.org/4d32b88095a6509da511
Search for TODO
The Composer class is the part im implementing, leveraging the Email class i created.
Add some text to the Subject, and then click the "Send" button
Your Email class' constructor
Email( List<String> to, String from, {String subject:null, String message:null, DateTime datetime:null, HashMap<String, List<String>> meta:null, List<Attachment> attachments:null}) { ... }
has 2 positional arguments and 5 optional named arguments.
You can simply pass positional parameters like you did in
new Email(map["to"], map["from"], map);
but optional names parameters need to be "named" like
new Email(map["to"], map["from"], subject: map);
If you want the optional parameters to be positional you need to change the constructor to
Email( List<String> to, String from, [String subject=null, String message=null, DateTime datetime=null, HashMap<String, List<String>> meta=null, List<Attachment> attachments=null]) { ... }
You can't have optional named and optional positional arguments at the same time. If you have a longer parameter list like in your Email constructor, named optional arguments are usually better because you can specify with a name which parameter the passed value should be assigned to and there is no need to pass nulls or ''s for parameters you want to skip.
I'm building a plugin for Jenkins and I'm trying to validate my form (connection test method). This worked fine when all #QueryParameter were Strings.
Now I'm trying to send my form validation method an Object like this:
public FormValidation doTestConnection(
#QueryParameter("url") final String url,
#QueryParameter("timeout") final String timeout,
#QueryParameter("bypassProxy") final boolean bypassProxy,
#QueryParameter("deployerCredentialsConfig") final CredentialsConfig deployerCredentialsConfig,
#QueryParameter("resolverCredentialsConfig") final CredentialsConfig resolverCredentialsConfig
) throws ServletException {
In my global.jelly file I have this:
<f:validateButton
title="${%Test Connection}" progress="${%Testing...}"
method="testConnection"
with="url,timeout,bypassProxy,deployerCredentialsConfig,resolverCredentialsConfig"/>
My CredentialConfig class implements Serializable but I guess that is not enough becuase I'm getting this when clicking the "Test Connection" button:
java.lang.IllegalArgumentException: Failed to invoke public hudson.util.FormValidation
org.jfrog.hudson.MyBuilder$DescriptorImpl.doTestConnection(java.lang.String,java.lang.String,boolean,org.jfrog.hudson.CredentialsConfig,org.jfrog.hudson.CredentialsConfig) throws javax.servlet.ServletException
Jenkins has no good documentation for using objects inside of FormValidation calls.
Looking at the Jenkins documentation and the code behind <f:validateButton/>, I believe it's impossible have objects bind in validation logic.
The docs say (https://wiki.jenkins-ci.org/display/JENKINS/Jelly+form+controls):
The 'with' attribute specifies the input fields sent to the server for
the validation. They are matched against the field attribute or the
name attribute of other input controls. The values of the nearest
input fields above the are sent to the server, so
this means the button has to come after the input fields. Multiple
fields can be specified by using ','.
The code simply gets fields by the names - there is no "object assembly" (I believe it's only done during actual config submission).
https://github.com/jenkinsci/jenkins/blob/96ec7a267e0efba2ec99590c871db0940e35920f/war/src/main/webapp/scripts/hudson-behavior.js#L2856
I bumped into a similar problem. Looking at the code, it seems stapler tries to convert your parameter to the type you provided in the doCheck function declaration.
class HandlerImpl extends AnnotationHandler<QueryParameter> {
public Object parse(StaplerRequest request, QueryParameter a, Class type, String parameterName) throws ServletException {
String name = a.value();
if(name.length()==0) name=parameterName;
if(name==null)
throw new IllegalArgumentException("Parameter name unavailable neither in the code nor in annotation");
String value = request.getParameter(name);
if(a.required() && value==null)
throw new ServletException("Required Query parameter "+name+" is missing");
if(a.fixEmpty() && value!=null && value.length()==0)
value = null;
return convert(type,value); // <--- HERE
}
}
As a workaround, I changed the type to boolean, like so:
public FormValidation doTestConnection(
#QueryParameter("url") final String url,
#QueryParameter("timeout") final String timeout,
#QueryParameter("bypassProxy") final boolean bypassProxy,
#QueryParameter("deployerCredentialsConfig") final boolean deployerCredentialsConfig,
#QueryParameter("resolverCredentialsConfig") final boolean resolverCredentialsConfig
) throws ServletException {
This allows me to at least check if the variable is set. It might not be enough for your use case, though.
I have tried to pass dynamic parameters to keyvalue(message to display) which I will get from package.properties to the Action class through the getText() method. To get the message, we can use getText(String keyvalue) method. What should I do to pass some parameters and retrieve the parameters with the message through the getText() method?
I saw some API's to pass dynamic parameters. But I don't know how to use, these are the following API's, click here to see the Struts 2 API Documentation.
getText(String aTextName, List<Object> args)
getText(String key, String[] args)
getText(String key, String defaultValue, String[] args)
Thanks in advance..
I suppose that you have following properties in your package.properties
username.required=user name is required
password.required=password is required
you can use getText() as
getText("username.required")
getText("password.required")
Now if we want to use getText(String key, String[] args) we have to pass following parameters
aTextName - the resource bundle key that is to be searched for
args - a list args to be used in a MessageFormat message
That means the message format pattern and other static strings will, of course, be obtained from resource bundles. Other parameters will be dynamically determined at runtime.
example
we have following entry in resource file
disk.data=The disk \"{0}\" artist name is {1}.
in this {1} and {0} are the dynamic parameters and will be determined at run time so args will contain the value of these parameters.
String artistName= demo;
String diskName = "Artist";
String[] testArgs = {artistName, diskName};
So final call will be getText(disk.data, testArgs);
and it will show
The disk demo artist name is Artist.
Please go through MessageFormat to know how this work
HI:
When using a form,the parameter form the clien can be bound to an object,for example:
processing-forms.html
In the client:
<s:form action="register">
<s:textfield name="personBean.firstName" label="First name" />
<s:textfield name="personBean.lastName" label="Last name" />
<s:textfield name="personBean.email" label ="Email"/>
<s:textfield name="personBean.age" label="Age" />
<s:submit/>
</s:form>
In the severside:
public class Register extends ActionSupport {
private static final long serialVersionUID = 1L;
private Person personBean;
//................
}
Then the parameter of the client are bound to the personBean instance.
Now,my problem is how to bind the parameters without a from?
My action work as a service which will be called in the javascript,so how to bind them?
I know how to get the parameters:
Map(String,Object) map=ActionContext.getContext.getParameters();
String firstName= map.get("firstname")[0];
//..........
This is too ugly :(
UPDATE
public class ParaWrapper(){
private String firstName;
public void setFirstName(String ..){
this.firstName=...
}
//the getter of firstName
public ....
}
public MyAction extends ActionSupport{
private ParaWrapper wrapper;
public void setXXX()...
public void getXXX()...
public void execute(){
System.out.println(wrapper); //here I can not get the parameters,it seems that the parameters are not poputed to this object.
}
}
Since I do not use the s:form tag,so How do struts know where to put the paramters ?
You handle it the same way. If your field is named firstname, then you will need a setFirstname method on the action. Whether the parameters are coming from a form or from JavaScript is irrelevant.
Update
Based on your revised code example, you will need a getWrapper method on your action to expose the ParaWrapper object.
You can avoid the "wrapper." prefix by implementing the ModelDriven interface and making ParaWrapper your model. Then you would just have parameters such as: firstName, lastName, etc (whatever fields are on ParaWrapper).
I think you shouldn't use private fields for the values that should be set via Struts2.
Explanation:
I don't know how you post the parameters to your action via JavaScript, but it should work if you add the necessary parameters to the URL you call. You can possibly call (as suggested in the mailing list):
http://yourdomain/yourstruts.action?personBean.firstName=a_string&personBean.lastName=my_lastName& ... (more person parameters)
Struts2 will understand the dot-notation and try to set the personBean variable in your target action. If this is of a Bean class (with an empty public constructor and public setters for each parameter), it will generate a new object and call the setters with the parameters. If it cannot access the parameters, nothing can be set.
So, if your setters are public and your PersonBean class is defined correctly, a PersonBean should be in your actions personBean field.
Hope this helps.