Multi page form data validation in Play Framework? - forms

I am a beginner in java play framework. I an building an app which will take form data spread in multiple pages say 4 to 5 pages. But all the data is mapped to same model. How can I get the data uploaded by user per page, validate against my model's constraints, and at the end save whole data in my model.
For ex:- If page 1 has name field which is required, and page 2 has hobbies field which is required. Then how can i specifically validate data filled in that particular page, navigate till last page, and save all the data in model, in last page.
Model would have 60-70 fields.
I am using Hibernate ORM.
Thanks !

You could prefill the next form with the values of the last form, save them in the database, go to the next form, load the entered values from the values and pre-fill the next form and so on. For this, use a method in your controller:
public static Result fillOutForm1(){
Hobby form1 = new Hobby("sitting still", "diabetes");
Form<Hobby > preFilledForm = newHobbyForm.fill(form1);
return ok(views.html.YOURVIEWCLASS.render(preFilledForm);
}
With this you "send" some values to the first view class with a form. In there, the user answers some more fields and hits Submit.
So you need a route back to your controller, to handle the new input in routes.conf:
GET /Form1 controllers.Application.fillOutForm1()
POST /Form1 controllers.Application.sendForm1()
This is in your controller class:
public static Result sendForm1(){
Form<Hobby> boundHobby = newHobbyForm.bindFromRequest();
Hobby newHobby = boundHobby.get();
//In your hobby class you need a finder implementation, so that you can interact with the database. With save() you put it into the database. This may be different for the database you use!
newHobby.save();
return redirect(routes.Application.index());
}
You can then not redirect to the index, but to the next view class with the next form and there get your last answers from the db, prefill them again and put them into the form. Do this as often as you need.

Related

Pass parameter to virtual entity data provider plugin

I'm aiming to show virtual entity records on a subgrid on the form of a custom entity (say, Client). I have created a virtual entity, custom data provider and registered the required plugin. So far things work fine; I load the form, subgrid loads with the data from external webservice.
Now, I want to pass a string field on the form (say, Client.ExternalId) as a parameter to the retrieveMultiple plugin so that I can use this field to query the datasource.
The retriveMultiple plugin steps (registered automatically when custom data provider was set up) show that it was registered on the virtual entity and not Client entity. Since it gets executed on load of the subgrid on the Client entity form I am not sure how I can pass a field to the plugin.
Can someone please give some guidance on how to achieve this?
Version 1710 (9.2.22103.194) online
Thanks
If the virtual entity has an N:1 relationship with the main entity and the subgrid is configured to show related records, then you can do like this:
// first, get the whole query
var query = context.InputParameterOrDefault<QueryExpression>("Query");
// next, get the linkEntity and then the linkFilter
var linkFilter = query.LinkEntities.FirstOrDefault(x => x.LinkToEntityName == "mainEntityLogicalName").LinkCriteria;
// next, get the main entity id
var mainEntityId = linkFilter.Conditions.FirstOrDefault(x => x.AttributeName == "mainEntityIdFieldName").Values.FirstOrDefault() as Guid?;
// finally, retreive main entity to get the Client.ExternalId
var mainEntity = orgSvc.Retrieve("mainEntityLogicalName", mainEntityId.Value, new ColumnSet("Client.ExternalId"));
var clientExternalId = mainEntity.GetAttributeValue<string>("Client.ExternalId");

Wicket form with list of all available values

Suppose we have following entities (representing a m:n relation, with additional column on the join table):
public class User {
private String name;
private List<Login> logins;
}
public class Login {
private User user;
private Website website;
private String login;
}
public class Website {
private String name;
private List<Login> logins;
}
I want to create a User edit form that contains one login input field per each existing website (so that all existing websites are in the form). E.g., having 2 websites defined (website1, website2), I would like to see:
My problem is with achieving following behavior on submission of the form: if login input field is filled for a website, it should be added to user1's logins, and if it's empty, it should not be added/get removed.
I created the form using User model (for user name), and website's fields use ListView backed by a model of all logins (taken straight from DB). This makes my form look as expected, but the behaviour is not there, as websites model is independent from the User model. What is your recommended approach?
Use a ListView backed by a list of all possible Login objects, ie the existing Login object if it exists and a dummy/empty/new Login object for each Website for which it doesn't exist.
Then on form submission save those Login objects which have a not-null and not-empty login field.
You could create a bean instead of directly using the Login object but it would work the same way.
If you also want to delete Login objects for which the user removed the login value, create some way in which you can check the Login object has been saved before (ie, its login field was notempty once) and delete the object if it is empty now.
Changing ListView to PropertyListView did the trick. Model gets updated properly and therefore I can do any required postprocessing in onSubmit(). With the ListView, form was rendered fine, but changes in login input fields were ignored.

Foreign entity in form into different kind of input

I have two entities: product and category (Symfony 2.3).
I want to create a form in which an user can choose a product by first selecting the category. A user selects the category by clicking on image, then I want to set the image's value into a hidden input, but I don't see how can I change a foreign entity choice list to a hidden input (http://symfony.com/doc/current/reference/forms/types/entity.html).
How can I accomplish this? (how to change form input to hidden)
If I set cascade validation to true, will it for example check if a category really exist. (To prevent putting products with non-existing category from malicious users) ?
Part 1
To do this you need to use a data transformer to do two things:
transform an entity into an identifier that is either a string or integer so a form can render it as a hidden field.
transform the string or integer identifier into the entity when the form is submitted so that the parent entity can be saved with the correct relationship
The symfony docs I linked to above (here too) actually walk though an entire example of using a data transformer with a form.
As a shameless plug (because I believe it is helpful) I have written a little tutorial on using a data transformer for a hidden field with an entity id: http://lrotherfield.com/blog/symfony2-forms-entity-as-hidden-field/
Part 2
If you are using the data transformer then you don't need to worry about malicious users. The data transformer will fail because it will not be able to reverse transform the category from the fake id. In my tutorial the transformer will throw a Symfony\Component\Form\Exception\TransformationFailedException exception.
You can also write a validator (potentially using a call back) if you wanted that checks that the submitted category is real if you want an error to show in the form. Doctrine wont allow you to persist a fake category relationship as the foreign key constraint will fail.

Laravel eloquent has_many_and_belongs_to sync() without writing to database

In short, does Laravel's eloquent have something like it's sync() functionality that doesn't save the relationships to the database right away?
I have two models
Place (id, name, address);
and
Feature (id, name);
These two models has a has_many_and_belongs_to relationship with each other, using the pivot table
feature_place(place_id, feature_id). This works as expected. Now I'm trying trying to build a form for creating a new Place. The form contains a checkbox for each existant Feature. For error handling I want to be able to create a Place object when the form is submitted. I'd like to be able to create my HABTM relationship, so I can easily rebuild and fill the form if submission fails (validation error or similar). sync() would usually handle the relationships, but since the submission has failed I don't want to insert the Place in the database yet.
Is there an easy way, like sync(), to create the relationship between my Place and it's Features that I can use to repopulate my form on rebuild, without having to write to the database before form submission succeeds?
It sounds like you need to flash the input to the session and then load the old values when the form is rendered.
// Somewhere in your post route
if ( $oh_noes_teh_validator_failed )
{
Input::flash();
Redirect::to_route( 'my-edit-form' );
}
// Somewhere in your edit route or view
$title = Input::old( 'title', $title );

How to make Symfony2 entity formtype show entities of type A but save them as type B?

I currently have the option in my application for a user to select favorite Items from a list. The form element is of type Entity and shows the list of objects. Users can select a number of them as their personal favorite.
However, although the list must show Items, what has to be stored is actually a FavoritedItem (which contains extra information about when/how the user favorited his Item).
I cannot figure out how to convert the entity types so that the user can pick from a list of Item entities but that the form stores FavoritedItems connected to the user.
I guess your entity has a relationship with FavoritedItem, when you are creating your form, don't include that field, but a dummy field to contain the data the user selected:
$builder->add('favs', null, array('property_path' => false, 'type'='entity'.....));
Find this line:
if ($form->isValid()) {
// perform some action, such as saving the task to the database
return $this->redirect($this->generateUrl('task_success'));
}
and for each of your items, set the appropriate FavoritedItem on your entity. It would look something like:
$favorites = $form->get('favs')->getData();
foreach($favorites as $f){
$FavItem = new FavoritedItem($f);
$yourEntity->addFavorite($FavItem);
}