I'm using the Play Framework and I've got the common use case to update a model with a form in a controller action. But I've some issues understanding the concept behind it because this is just working if you have a form which includes ALL of the properties of the model. If you have a just a partial form, e.g. editing just a password of a user model, this method destroys the model, because it sets the other properties of the model to null. Is there any "official" solution to that problem? Any way Play updates just the existing properties?
public static Result update(Long id) {
Model model = Model.findById(id);
Form<Model> filledForm = modelForm.bindFromRequest();
if (filledForm.hasErrors()) {
return badRequest(edit.render(filledForm));
} else {
model.update();
flash("message", "Created new Model!");
return ok(index.render());
}
}
Probably the solution lays somehow in the fact that the bindFormRequest() method can be called with additional parameters, like Strings or a Map of Strings? But I can not find out the purpose of that. Some insight into that would be great as well. Thanks a lot!
Changing the default Content-Type Will automatically set the Content-Type header to text/plain , while: JsonNode json = Json. toJson(object); Result jsonResult = ok(json); will set the Content-Type header to application/json .
Play Framework is an open-source web application framework which follows the model–view–controller (MVC) architectural pattern. It is written in Scala and usable from other programming languages that are compiled to JVM bytecode, e.g. Java.
sbt : The sbt settings that describe building your application. /conf : Configuration files for your application. /project : Further build description information. /public : Where static, public assets for your application are stored. /test : Where your application's test code will be stored.
Play Framework makes it easy to build web applications with Java & Scala. Play is based on a lightweight, stateless, web-friendly architecture. Built on Akka, Play provides predictable and minimal resource consumption (CPU, memory, threads) for highly-scalable applications.
On a recent project, I needed this kind of feature and I had to reimplement the Form class (based on the original Play Form) to allow an additional parameter to the bindFromRequest()
method.
Taking your code as an example, it would become something like this :
Model model = Model.findById(id);
Form<Model> filledForm = CustomForm.form(Model.class).bindFromRequest(model);
The idea is to only modify the fields defined in your form and keep the other fields of your model unmodified.
To allow this specific binding, you have to redefine the bind(Map<String,String> data, String... allowedFields)
method (along with the bindFromRequest
) with something like this :
public Form<T> bind(T instance, Map<String,String> data, String... allowedFields) {
DataBinder dataBinder = null;
Map<String, String> objectData = data;
if(rootName == null) {
dataBinder = new DataBinder(instance);
} else {
dataBinder = new DataBinder(instance, rootName);
objectData = new HashMap<String,String>();
for(String key: data.keySet()) {
if(key.startsWith(rootName + ".")) {
objectData.put(key.substring(rootName.length() + 1), data.get(key));
}
}
}
Instead of creating the DataBinder
with blankInstance()
as the standard Play Form class does, you create it with you model instance as the constructor argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With