easy way of showing errors in a wicket form - wicket

I am a wicket beginner and find it extremely hard to implement more advanced actions in it.
So I've got a form with input fields in it and a submit button. I've written my own validator with its own logic. now when the validator fails the page simply reloads and the wrong value is lost. what I want is:
inputs with wrong input(where the validator failed) should be graphically different, that is get its own style - can i do it in the validator itself? or do I have to implement a visitor? how do i register it for this very form? No error message is necessary.
the 'wrong input' should not be lost and should be visible to the user.
I'd be eternally thankful for a simple solution (with some code snippets please)

What you need is a Validator + Behavior.
The behavior is needed to modify the FormComponent's markup when it is invalid.
Fortunately they mix very well:
public class MyValidator extends Behavior implements IValidator<SomeType> {...}
Implement IValidator#validate(IValidatable) to validate (you already have this) and override Behavior#onComponentTag(Component, ComponentTag) to set a CSS class when invalid, e.g.:
#Override public void onComponentTag(Component c, ComponentTag tag) {
FormComponent fc = (FormComponent) c;
if (!fc.isValid()) {
tag.append("class", "error", " ");
}
}
Make sure you have a .css file loaded that defines .error with the desired styles. You can override Behavior#renderHead(Component, IHeaderResponse response) {response.render(CssHeaderItem.forReference(new CssResourceReference(SomeScope.class, "res/css/styles.css")))} for that.
I hope things a cleaner now.
Have fun!

Related

Flutter best practice for form submissions

I am having trouble finding good resources for what best practices would be for Flutter development, specifically for form handling.
Everything I find on form submissions is fairly clear, but the problem is they all have the validation logic and submission logic directly in the form widget. I don't like this as it seems it would get very convoluted very quickly with more than say 3 inputs and any sort of more than basic validation logic. It also seems to violate the separation of concerns thinking that I though was supposed to be a big thing in Flutter/Dar (at least from what I have read).
So my chosen solution for this was my FormHandler class, which I defined in the form_handler.dart file. It has some static methods for validation of input, some methods for submission handling, and a formInput of type Map<String, dynamic> for storing key value pairs of user input.
It works like this:
An instance of the FormHandler is created
The user inputs the data
On form.save(), for each user input, the input data is stored in the formInput map, with key being the title of the input, and the value being the user's input.
The submission button would run the validation and save functions and then take the data from formInput and send it to something like a database handler that would store it on the db
form_handler.dart:
class FormHandler {
// make new form handler with empty map
FormHandler({required this.formInput});
// for storing input key value pairs
Map<String, dynamic> formInput;
// Form submissions
// new course
void submitCourse({required formKey}){
final form = formKey.currentState;
// save on validate
if( form.validate() ){
form.save();
// then make new course via the database controller
}
}
// Input validations
static String? validateTextInput(String? input){
if( input == null || input.isEmpty ){
return 'Field must not be empty';
} else {
return null;
}
}
}
I'm just wondering if this is a good solution, what are some potential pitfalls, any suggestions etc.
It seems like a good solution to me, but I would like feedback from someone with more experience than me.
Thanks, Seth.
A common practice would be to create value objects or entities that hold logic to do validation on themselves. Perhaps with an interface (abstract class) as a base for those to make sure that you don't forget to implement such validation.
Thereby moving such validation logic from the UI and instead caring about what is important in your domain. It will be possible to validate in several places in your code, not just from the form, which is not something easily achievable with your proposed solution. Your solution still mix UI with logic via the formKey. You might want to validate "stuff" when you receive data from your backend, or do other calculations/changes to values later in the app.
You can refer to this youtube channel for guidance.
Here is a link for a video related to TextFields and Validation - https://youtu.be/2rn3XbBijy4

Apache Isis: How to implement your custom submit form or page properly?

I'm new at Apache Isis and I'm stuck.
I want to create my own submit form with editable parameters for search some entities and a grid with search results below.
Firstly, I created #DomainObject(nature=Nature.VIEW_MODEL) with search results collection, parameters for search and #Action for search.
After deeper research, I found out strict implementations for actions (For exapmle ActionParametersFormPanel). Can I use #Action and edit #DomainObject properties(my search parameters for action) without prompts?
Can I implement it by layout.xml?
Then I tried to change a component as described here: 6.2 Replacing page elements, but I was confused which ComponentType and IModel should I use, maybe ComponentType.PARAMETERS and ActionModel or implement my own IModel for my case.
Should I implement my own Wicket page for search and register it by PageClassList interface, as described here: 6.3 Custom pages
As I understood I need to replace page class for one of PageType, but which one should I change?
So, the question is how to implement such issues properly? Which way should I choose?
Thank you!
===================== UPDATE ===================
I've implemented HomePageViewModel in this way:
#DomainObject(
nature = Nature.VIEW_MODEL,
objectType = "homepage.HomePageViewModel"
)
#Setter #Getter
public class HomePageViewModel {
private String id;
private String type;
public TranslatableString title() {
return TranslatableString.tr("My custom search");
}
public List<SimpleObject> getObjects() {
return simpleObjectRepository.listAll();
}
#Action
public HomePageViewModel search(
#ParameterLayout(named = "Id")
String id,
#ParameterLayout(named = "Type")
String type
){
setId(id);
setType(type);
// finding objects by entered parameters is not implemented yet
return this;
}
#javax.inject.Inject
SimpleObjectRepository simpleObjectRepository;
}
And it works in this way:
I want to implement a built-in-ViewModel action with parameters without any dialog windows, smth like this:
1) Is it possible to create smth like ActionParametersFormPanel based on ComponentType.PARAMETERS and ActionModel and use this component as #Action in my ViewModel?
2) Or I should use, as you said, ComponentType.COLLECTION_CONTENTS? As I inderstand my search result grid and my search input panel will be like ONE my stub component?
Thank you.
We have a JIRA ticket in our JIRA to implement a filterable/searchable component, but it hasn't yet made it to the top of the list for implementation.
As an alternative, you could have a view model that provides the parameters you want to filter on as properties, with a table underneath. (I see you asked another question here on SO re properties on view models, so perhaps you are moving in that direction also... I've answered that question).
If you do want to have a stab at implementing that ticket, then the ComponentTYpe to use is COLLECTION_CONTENTS. If you take a look at the isisaddons, eg for excel or gmap3 then it might help get you started.
======= UPDATE TO ANSWER (based on update made to query) ==========
I have some good news for you. v1.15.0-SNAPSHOT, which should be released in the couple of weeks, has support for "inline prompts". You should find these give a user experience very similar to what you are after, with no further work needed on your part.
To try it out, check out the current trunk, and then load the simpleapp (in examples/application/simpleapp). You should see that editing properties and invoking actions uses the new inline prompt style.
HTH
Dan

testNG: sending report via mail within the #AfterSuite section

I'd like to send the report generated by testNG ( java+eclipse+testNG) within the #AfterSuite section.
It's not a problem to send it, but the point is that the report is generated after the #AfterSuite section, so , basically, i send the previous one instead of the last one !
Any idea about how can I solve it ?
As you are seeing, #AfterSuite runs before the report is generated.
Have you though about implementing a TestNG IReporter listener ?
public class MyReporter implements IReporter {
#Override
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> iSuites, String s) {
//Create your bespoke results
//Email results
}
}
Obviously you can see a flaw in that you have to generate your own results from the raw results data (which may be advantageous if you just want to email a subset of data).
The ideal solution would to be able to extend the default report generator, but I am not sure this can be done. However there is an existing listener provided by http://reportng.uncommons.org/, which actually provides a much nicer report output.
If you extend this this class, and call their code, and then add email generator code afterwards, it may work
public class MyReporter extends HTMLReporter {
#Override
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> iSuites, String s) {
super.generateReport(xmlSuites, iSuites, s);
//Email results
}
}
You can attach a listener to a test suite in several ways, as explained on the TEstNG website (http://testng.org/doc/documentation-main.html#listeners-testng-xml)
An alternative to all of this woudl be to use a build tool like Maven to run your tests, then have a post test event to email the results.
I copied the answer from Krishnan.
It works for me.
By the way, in my test environment, I need to extends the org.testng.reporters.EmailableReporter2 instead of EmailableReporter to make sure the correct count.
See below for your reference:
Krishnan Mahadevan Krishnan Mahadevan at Jul 31, 2012 at 8:58 am I am guessing that you are referring to the TestNG generated
"emailable-report.html" which you would want to mail.
With that assumption here's how you should be able to do it.
Extend org.testng.reporters.EmailableReporter
Override org.testng.reporters.EmailableReporter.generateReport(List,
List, String) and have it do something as below :
#Override
public void generateReport(List xml, List suites, String
outdir) {
super.generateReport(xml, suites, outdir);
SendFileEmail e= new SendFileEmail();
e.sendEmail();
}
Now add up this listener of yours into your suite file using
tag.

Suppress Errors in JavaScript validation

I'm currently developing an eclipse plugin. This plugin contains a project nature which depends on the javaScript nature of jsdt.
Now at a few details the JavaScripts that the projects of my nature can contain are somewhat special.
They can contain "compiler hints" which are basicly statements beginning with #
They can contain return statements outside of functions
But at this two points the standard validation of jsdt come in and marks them as errors (which is normally right). I already managed to get this errors filtered out in the properties of the JavaScript validator (manually).
My question is, how can i exclude these errors from the validation of jsdt automatically for the projects with my nature?
JSDT uses concrete syntax parser which generates syntax errors.
You can't disable this. Only semantics error or warnings can be configured.
However you can disable entire validation of JSDT.
Below solution will suppress errors ands warnings which are generated while we save some changes on java script files. (Auto Build, Build)
Open Properties Dialog of Your Project.
Choose Builders item.
Uncheck "JavaScript Validator". And Press OK button.
Remove current errors and warnings from Problems View
This solution can't eliminate error or warning annotations in editor while you edit. They will show up on editor temporarily only when you edit it.
After a lot of research, hours of deleting markers and debugging i finally managed to delete the errors i wanted. In a bad bad way of course but i've come to a point where i just wanted this to work no matter how it's done.
If you ever want to delete existing problems that had been created during the validation process of jsdt you need to do the following (and you must not ommit anything):
Create a class extending org.eclipse.wst.jsdt.core.compiler.ValidationParticipant
Override isActive(), buildStarting() and reconcile() methods.
So there are two things you basicly have to care about.
The actual problem markers that will be created or had already been created at the end of the validation process.
The Problems created by the validation process. They are of the type CategorizedProblem and can be obtained by the ReconcileContext object that is passed to the reconcile() method.
It seems to me that the CategorizedProblems will be translated to problem markers after the validation process.
So what you need to do is:
Delete all unwanted problem markers of all files in buildStarting (this removes problem markers from all files in your project that are about to be validated)
Iterate the CategorizedProblem objects of the ReconcileContext (getProblems())
Create a new Array containing only the CategorizedProblems you want to keep
Set this new Array to the ReconcileContext with putProblems()
Delete the unwanted markers again for that file (i don't know why this is needed, please don't ask, i don't care anymore :-/)
An example implementation of such a validationParticipant could look like this: (this one will filter out problems complaining about return statements outside of methods:
[...ommited imports ...]
public class MyValidationParticipant extends org.eclipse.wst.jsdt.core.compiler.ValidationParticipant{
#Override
public boolean isActive(IJavaScriptProject project) {
return true;
}
#Override
public void buildStarting(BuildContext[] files, boolean isBatch) {
super.buildStarting(files, isBatch);
for(BuildContext context : files){
IFile file = context.getFile();
deleteUnwantedMarkers(file);
}
}
#Override
public void reconcile(ReconcileContext context) {
IResource resource = context.getWorkingCopy().getResource();
CategorizedProblem[] newProblems = new CategorizedProblem[0];
ArrayList<CategorizedProblem> newProblemList = new ArrayList<CategorizedProblem>();
CategorizedProblem[] probs = context.getProblems("org.eclipse.wst.jsdt.core.problem");
if(probs != null){
for(CategorizedProblem p : probs){
if(!(p.getMessage().equals("Cannot return from outside a function or method."))){
newProblemList.add(p);
}
}
}
}
context.putProblems("org.eclipse.wst.jsdt.core.problem", newProblemList.toArray(newProblems));
deleteUnwantedMarkers(resource);
}
public static void deleteUnwantedMarkers(IResource resource){
if(resource.isSynchronized(IResource.DEPTH_INFINITE)){
try {
IMarker[] markers = resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
if(markers != null && markers.length > 0){
for(IMarker m : markers){
Object message = m.getAttribute(IMarker.MESSAGE);
if(message.equals("Cannot return from outside a function or method.")){
m.delete();
}
}
}
}catch (CoreException e) {
e.printStackTrace();
}
}
}
}
As i said, this is kind of a bad solution since the code relies on the String of the error message. There should be better ways to identify the problems you don't want to have.
Don't forget to add a proper extension in your plugin.xml for the ValidationParticipant.

authorization on wicket component using wicket auth-role

I am using wicket 1.4.9 and implemented spring + wicket auth-role and using #AuthorizeInstantiation based on roles on pages. I have multiple custom roles.
I have followed this link to implement the basics:
https://cwiki.apache.org/WICKET/spring-security-and-wicket-auth-roles.html
After that I have implemented my own UserDetailsService to have my own roles/users from database.
Now, How can I impose controls on roles with components eg, Links,Buttons ? like
link A can be accessed only by SUPER_USER, DR_MANAGER. (roles comes from database).
I have done like this and it seems to work, but is that the good way to do this? OrbitWebSession is of type AuthenticatedWebSession.
#Override
public boolean isVisible() {
if(OrbitWebSession.get().getRoles().hasRole("SUPER_USER")){
return true;
}
return false;
}
thanks.
Overriding isVisible all the time is a major pain. Take a look at MetaDataRoleAuthorizationStrategy instead. You call authorize(Component component, Action action, String roles) with Action RENDER, and the roles you want to allow. This way the component, whatever it is, is automatically hidden for other roles provided that the authorization strategy is registered in your webapplication. Basically it does the same thing as Holms answer, except you don't have to subclass anything.
You are in the right track, the only change I would do is:
#Override
public boolean isVisible() {
return super.isVisible() && OrbitWebSession.get().getRoles().hasRole("SUPER_USER");
}
That way you don't accidentally override its default visible behavior for example if the parent component is not visible.
Using the #AuthorizeAction annotation you can control wether the component is rendered or not based on roles. It's quite easy to use, but you have to subclass the component that you want to authorize.
#AuthorizeAction(action = Action.RENDER, roles = { "SUPER_USER", "DR_MANAGER" })
class UserAdminPageLink extends BookmarkablePageLink<String> {
//Implementation…
}
add(new UserAdminPageLink("UserAdminPageLink", UserAdminPage.class));
Check out Wicket Examples - Authorization for some working code.