Can a lift form accept attributes for multiple models? - scala

In Rails I can use accepts_nested_attributes_for to allow a single form to create two different but related objects. Now, I'm working on a Scala Lift project and I want to do something similar. I have a User model and an Address model. I want to have a single form that creates the User and their Address. How does this work in Lift?

In general, Lift approaches form processing by binding a handler function to each input which is called on form submission. In each of those functions, you would define the logic you need to set the appropriate fields in your model.
Using something like the example below you can instantiate your classes and then perform the appropriate action on submission. You will see this creates a User and an Address class and then sets a field on each of them. The function bound to the submit button will take care of persisting them both. Since the actions happen in a function, you can include as much logic as necessary to make your application work (data transformation, setting multiple fields, etc...). For example, in the submit logic I associate the id of the Address with the User to define how they are related.
In your Snippet
val user = new User()
val address = new Address()
".nameField" #> SHtml.input(user.name, (txt) => {
user.name = txt
}) &
".addressField" #> SHtml.input(address.address1, (txt) => {
address.address1 = txt
}) &
".submit" #> SHtml.submit("Save", () => {
//persist address
user.addressId = address.id
//persist user
})
In your HTML
<form data-lift="form">
<input class="nameField"></input>
<input type="submit" class="submit"></input>
</form>
In general, that is how you would accomplish what you are looking to do. In addition to handling everything yourself, Lift includes Mapper which is pretty much a database ORM. I believe that can automate a lot of the relation mapping and make the creation of some forms easier. I don't really use it myself, so I can't give you a more concrete example. But, if you decide to check that out, you can find more information on Mapper here and here.

Related

SAPUI5 No dynamic way to get form data without data binding. And no Form submit event.

I have a simple form that's in a dialog fragment used to submitting two fields for log-in auth.
For simplicity I was hoping to not have to use data binding, but rather use some method to gather all data inside my sap.ui.layout.form.SimpleForm.
I added a name property to each input element which says in the docs it is " Defines the name of the control for the purposes of form submission."
https://openui5.hana.ondemand.com/#/api/sap.m.InputBase/controlProperties#name
However hard as I try to find there doesn't seem to be any getFormData methods.
All SO questions and guides either use data binding to a model, or hard-code references to the individual input controls with .getValue() methods.
And looking further into the form API, there doesn't seem to be a Submit event either.
Given an arbitrary form, what would be the best way to gather all submission values without hard-coded references or data-binding?
Would a method that walks though all the children elements of a form looking for all submission values work? I think it might, but there are more submission input types then just the input component.
You can get the value of the fields by directly using;
var oField = sap.ui.getCore().byId('IdOfTheFieldAtTheDialog');
var sValue = oField.getValue();
But it's always better and convenient to use data binding which keep things neat.
And If I assume that you have the id of parent form container, you can iterate over the items and get the sap.m.Input elements in it without knowing the IDs of the individual inputs, and you may check the name property of the fields if you want. Check this snippet;
https://jsfiddle.net/hdereli/9e92osfk/3/

Play! Framework Form/HTML Helpers: Separation of Concerns?

I just started playing around with Play 2.1.1 using Scala. Going through some tutorials/sample apps, I came across the helper methods that can be used to create forms, e.g.:
#(myForm: Form[User])
#helper.form(action = routes.Application.submit) {
#helper.inputText(myForm("username"))
#helper.inputPassword(myForm("password"))
}
I am still a n00b to this. But as far as I understand, this basically requires a form object being defined within the controller, which "wraps" the model (simplified):
val loginForm = Form(
tuple(
"email" -> text,
"password" -> text
))
)
def login = Action { implicit request =>
Ok(html.login(loginForm))
}
I found this suprising, as I get the feeling that the indirection through the Form object seems "in the wrong place". What I was expecting was something like this (pseudo):
#(user: User)
#helper.form(action = routes.Application.submit) {
#helper.inputText(() => user.userName)
#helper.inputPassword(() => user.password)
}
...so that one does not have to define the Form object within the controller; all form-related stuff would be located within the view template.
Mixing the "this-will-be-rendered-into-a-form" logic into the controller seems like a minor violation of SOC to me.
Now I'm wondering: Is this just the way things are done in Play, or did I miss something? Is there a "nicer" way to handle this?
Cheers, Alex
I think it would be annoying too with many form definition in controller, especially the apps will involved many form.
But Play!Framework make developer to write code more flexible. You can mix plain HTML inside scala template helper like this :
#helper.form(action = routes.Application.submit) {
<input type="text" name="username">
<input type="password" name="password">
....
}
In my opinion, the scala helper actually helpful with form to update data that have been created before. Because it will bind the existing value into the default input value. And additionally, it also help to display error that caused by object validation.
If the form is not considered the previous value, like login form, I think the use of plain HTML input will be considered better.

Zend creating forms based on requests within one controller/action

I don't really know how to word the title well, but here's my issue. I decided instead of having 25 controllers to handle pages, I have one PageController with a viewAction that takes in a :page parameter - for example, http://localhost/website/page/about-us would direct to PageController::viewAction() with a parameter of page = about-us. All of the pages are stored in a templates folder, so the viewrenderer is set to render application\templates\default\about-us.phtml.
I did this so I can consolidate and it seemed like a better approach. My question is the following: lets say when the page request is contact-us, I would need a Zend_Form to be used within the contact page. So, I would need a way within PageController::viewAction() to recognize that the page needs to have a form built, build the form, and also upon submission the need to process it (maybe this should be handled in an abstract process method - not sure).
I have no idea how to implement this. I thought maybe I can store a column with the name of a form and a connecting page identifier. Even better, create a one-to-many page to forms, and then in the submission loop through the forms and check if submitted and if so then process it (maybe there is a isSubmitted() method within zend_form. I really don't know how to handle this, and am looking for any help i can get.
Thanks!
Here is something that came to mind that may work or help point you in a direction that works for you.
This may only work well assuming you were to have no more than one form per page, if you need more than one form on a page, you would have to do something beyond this automatic form handling.
Create a standard location for forms that are attached to pages (e.g. application/forms/page). This is where the automatic forms associated with pages will be kept.
In your viewAction, you could take advantage of the autoloader to see if a form for that page exists. For example:
$page = $this->getParam('page');
$page = ucfirst(preg_replace('/-(\w)/ie', "strtoupper('$1')", $page)); // contact-us -> ContactUs
$class = 'Application_Form_Page_' . $page;
// class_exists will invoke the autoloader to map a class to a file
if (class_exists($class)) {
// a form is defined for this page
$form = new $class();
// check if form was posted
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost()) {
// form is valid - determine how to process it
}
}
// assign the form to the view
$this->view->pageForm = $form;
}
All this really leaves out is the action you take to process a specific form. Since the contact form will likely generate an email, and another form may insert data into a database, you will need some sort of callback system or perhaps another class that can be mapped automatically which contains the form processor code.
Anyway something along those lines is what came to mind first, I hope that helps give you some more ideas.

How can I use the sfValidatorEmail validator in Symfony to validate a single email field

I have a form with 2 elements that will be submitted and then update part of a user profile.
I don't want to use the entire generated form and have to remove all the fields except for the two I need. I just want to be able to create a quite simple form to do my update.
Is there a way to utilize Symfony's sfValidatorEmail inside the action on the returned value of an email field?
Since the regex is already written in the validator, I would like to reuse it, but I don't know how to use it in the action after the non-symfony form has been submitted.
Two approaches here - you could construct a simple form anyway extending from sfForm/sfFormSymfony (doesn't have to be ORM-based) that just contains the 2 fields you want. That way you can use the existing validation framework, and then use $myForm->getValues() after everything has been validated to get your values for your profile update.
Alternatively, as you've mentioned, you can use the sfValidatorEmail class in your action like so:
$dirtyValue = "broken.email.address"
$v = new sfValidatorEmail();
try
{
$v->clean($dirtyValue);
}
catch (sfValidatorError $e)
{
// Validation failed
}
The latter approach quickly leads to messy code if you have many values that need cleaning, and it's worth putting the logic back into a form to handle this in the usual manner.
If you're submitting a form with 2 elements, it should be a form on the edit and update end, period. Symfony forms are lightweight, there's no performance reason to not use them. Instead, make a custom form for this purpose:
class ProfileUpdateForm extends ProfileForm
{
public function configure()
{
$this->useFields(array('email', 'other_field'));
}
}

Loading models in Zend_Form using Zend Framework

I'm trying to build a form using the Zend_Form component, but the number of elements varies. The information for each Zend_Form element is stored in a database (name, options, validators, filters, etc.).
The application I'm working on consists of building surveys which contain a varying number of questions. Each question is associated with different arrays of answers. Ultimately my goal is to build arrays of radio/checkbox buttons, dynamically, server-side.
I'm looking for a pretty way to generate my form, but I'm not sure of the best way to load the model within the form. Should the model be loaded in the controller then passed (somehow, via a parameter?) directly to the form, or is it better to load the model within the Form init() method? Where's the best place to put the logic, should it be within the form class, or within the controller, or within the model?
My idea is to fetch form element properties (name, rules, filters, etc.) in the database, then iterate and finally render the form. What do you think of this approach? Ultimately, elements will be dynamically added (client-side), this time, using AJAX and a JavaScript library (such as jQuery).
Here are a couple useful links I found via Google, but I think they all answer a slightly different question than mine:
On building dynamic forms, server side:
http://framework.zend.com/wiki/display/ZFPROP/Zend_Form+generation+from+models+-+Jani+Hartikainen
http://weierophinney.net/matthew/archives/200-Using-Zend_Form-in-Your-Models.html
http://codeutopia.net/blog/2009/01/07/another-idea-for-using-models-with-forms/
On building dynamic forms, client side, with AJAX processing:
http://www.jeremykendall.net/2009/01/19/dynamically-adding-elements-to-zend-form/
I think I found a possible solution, it involves passing an array of Zend Form elements to the Zend Form::__construct() method. The constructor takes an array of options, one of them is called "elements". Have a look at the source code within the Zend Framework library.
I coded a new private method within the controller, called buildSurveyForm(). Note : the object, passed as a parameter, is built from a huge SQL query with half a dozen JOIN statements, fetching data from a few tables (surveys, questions, answers, etc.) within the database. One of the public attributes for this class consists of an array of questions, stored as objects (with public methods/attributes as well, etc.). Same for answers. The code for building these classes is pretty trivial and out of topic here.
Here's the code within the survey controller. I copy/pasted and edited/dropped a few lines to make it a lot clearer :
private function buildSurveyForm(MyApp_Object_Survey $survey)
{
foreach ($survey->questions as $question)
{
$element = new Zend_Form_Element_MultiCheckbox($question->order);
$element->addMultiOptions($question->getAnswersLabels());
$element->setName($question->order);
$element->setLabel($question->title);
$elements[] = $element;
}
// Here's the trick :
$formOptions = array('elements' => $elements);
$surveyForm = new MyApp_Survey_Form($formOptions);
$urlHelper = $this->_helper->getHelper('url');
$surveyForm->setAction($urlHelper->url(array(
'controller' => 'survey',
'action' => 'vote'),
'default'
));
$surveyForm->setMethod('post');
$this->_forms['survey'] = $surveyForm;
return $this->_forms['survey'];
}
The MyApp Survey Form class only contains a Submit button within the init() method. The dynamically generated elements with the code above are added BEFORE this submit button (which is unexpected, but useful). This class simply extends Zend_Form.
Then, within survey controller / view action :
public function viewAction()
{
$surveyModel = $this->_model['survey'];
$survey = $surveyModel->getFullSurvey($this->_getParam('id'));
$survey = new MyApp_Object_Survey($survey);
// Calls above private method :
$surveyForm = $this->buildSurveyForm($survey);
$this->view->assign(array(
'surveyForm' => $surveyForm,
));
}
Adding filters, validators and decorators to form elements is now trivial. My proposal is a bit dirty, but I think it gets the job done. I will add a new proposal if I find something more elegant. Feel free to post different answers/solutions.
You could extend Zend_Form.
Zend form is not good place for logic, only form representation.
So, Load all needed elements using model in controller and pass them to the form in contructor as parameters.