How to add fields that not defined in Entity? - forms

I want to add same additional fields to my form, but I don't want have ones in data object.
Here is an example:
$formBuilder = $this->get('form.factory')->createBuilder(new LeadType(), new LeadInfo());
$formBuilder->add('newsSubscribe', 'checkbox');
$form = $formBuilder->getForm();
But I get an error, because there is no 'newsSubscribe' field on my object, and I don't want add(because subscription has no relation to LeadInfo)
Is there a way to solve that?

The field type (which most form fields inherit by default) provides a property_path option that denotes which property on the domain object the field represents. You can tell your checkbox not to write to the domain object like so:
$formBuilder->add('newsSubscribe', 'checkbox', array(
'property_path' => false,
));
You may have to define other options for your checkbox as well, since you're passing an array that may overwrite default options, but that will get you started. With this code, newsSubscribe will be available in your POST variables, but Symfony won't attempt to write it to a domain object property.

Related

How to access backpack fields on custom (non-CRUD) page?

I've made a custom page in backpack admin panel. This page is non-CRUD (not related to any model). There are several forms on it, with date pickers, select inputs, etc. So I'am trying to find a way to use backpack fields to create these date pickers and select inputs. Because it seems to be awkward to embed custom js-controls into the project, as Backpack already has appropriate fields.
The only solution I came up with, is to create a crud controller for random model, disable all operations except create, use create operation view as custom page (backpack fields are available this way), and finally override store() method - to prevent creating new model entry in DB.
So, is there a proper way to access backpack fields on custom (non-CRUD) page?
Backpack 4.x fields aren't meant to be used outside CRUDs, but you can do that.
Option A
At their core, Backpack fields are just Blade views, so you can load them using the Blade helper #include(). Just make sure to pass along all variables that the blade file needs. I believe in 99% of the fields that will be a $field and a $crud variable, so this will work:
#php
// set the CRUD model to something (anything)
// but ideally it'd be the model of the entity that has the form
$crud = app()->make('crud');
$crud->setModel(\App\Models\Monster::class);
#endphp
#include('crud::fields.number', [
'crud' => $crud,
'field' => [
'name' => 'price',
'label' => 'Price',
'prefix' => '$'
]
])
This way, you only load the bits you actually want (the inputs), without the overhead of a CrudController. You can point the form to your custom controller and do the saving yourself. What you need to pass for a $field above is a Backpack field definition in array form.
This way is super-simple, but it has a big downside if you ask me. The field definition has to be 100% correct and complete, you lose all the magic and assumption logic that Backpack usually does to make your life easier when you add field using addField(). That's why in most cases I think it's more convenient to go with Option B.
Option B
Instead of manually loading all each field Blade view, add them using addField(), then load all of them just like Backpack does it in the Create or Update operation:
#php
$crud = app()->make('crud');
$crud->setModel(\App\Models\Monster::class);
$crud->addField([
'name' => 'price',
'label' => 'Price',
'prefix' => '$'
]);
#endphp
<form method="post">
#include('crud::form_content', [ 'fields' => $crud->fields(), 'action' => 'create' ])
</form>
The above will produce an output like this:
The benefit of this second option is that you can "forget" to mention stuff in the field definition and Backpack will assume it, you can use the fluent syntax, you can use most Backpack features, really...

Defining sort-order of associated model select box from CakePHP's FormHelper?

In this instance I'm working with two models: Departments, and Users.
Departments belongsTo Users
(In this instance, a user is a department manager [null allowed].)
Using FormHelper, I simply defined the selection of the User id as:
echo $this->Form->input('user_id', array('label'=>'Department/Group Manager (leave blank if none)', 'empty' => true));
By default, FormHelper seems to order the selection items by User.id ASC (the HTML select element's "value" property). To make things nicer in the add.ctp form, I created a virtual field as "Lastname, Firstname" to be used as the User model's display field:
public $virtualFields = array(
'name' => "CONCAT(User.lastName, ', ', User.firstName)"
);
public $displayField = 'name';
This worked great. Unfortunately, I'd love to be able to order the items in the rendered select box by the virtual field's value, ascending (or User.lastName in this case) instead of by User.id. I was unable to figure out a way to do this using FormHelper. Is there another way to do this (if FormHelper can't do it)?
MVC:
The MODEL retrieves the data (business logic).
The CONTROLLER sets the data for the view [$this->set()].
The VIEW simply handles your output, and any logic that is not capable of being handled elsewhere.
Using Cake convention based on how the cake bake output is created, you'd want to set the ORDER BY clause in the call to the model's find() method in your controller, related to the particular view. In this case, your Department's add() method.
public function add(){
// ... other code ...
$users = $this->Department->User->find('list', array('order' => array('lastName' => 'asc'));
$this->set(compact('users'));
}
Be aware that if you are using the Containable Behavior you may need to adjust its settings to achieve the default (most likely working) code example above.

MVC4 edit method changes values to null if correspndong fields don't exist in the form

My table has two columns CreatedBy and CreateTime. In my view form, I don't have these fields. Now when I update a record using ASP.NET MVC4 Edit (post) method, these columns are set to null. But I want to retain the values. I know in my Edit (post) method, I can retrieve the record from the database and set these manually. But I am wondering whether I can ask Entity Framework not to change the values of these fields.
No you can't, if you want to keep the old values then you have to get the record first and then manually assign the values that you want to update. The only other way is to go through your entity property by property and tag which ones you want to modify, like so:
db.MyEntity.Attach(myEntity);
db.Entry(myEntity).Property(e => e.MyProperty).IsModified = true;
db.SaveChanges();
either way you end up having to do the manual work yourself.
You have to choices here:
1) As #KennyZ mentioned, add to #Html.HiddenFor() somewhere in your view, into your form:
#Html.HiddenFor(m => m.CreatedBy)
#Html.HiddenFor(m => m.createTime)
2) You can manually update that entity and leave those two properties alone:
var ent = dbctx.Entities.Find(model.ID);
ent.Prop1 = model.Prop1;
// ... also for other properties except those two property
dbctx.SaveChanges();
Sure you can. I assume they are already in your model, just add them to the form with Html.HiddenFor(m => m.createdBy). Now they are in the form but not displayed, and still have values on Post methods.

Symfony2 Form : Select an entity or add a new one

I have an order and a client entity.
I am wondering if it's possible with the actual Symfony2 form system to create an order form which will allow to:
Select several clients from a dropdown (mix of collection and entity form type)
And to create new clients on the fly (the default way for the collection type) if not in the dropdown list.
I've seen some way to do it by creating multiple forms in the same page, but this is not the way I would like to achieve it.
Are there any better ways to do this?
I had a similar problem which may lead to your resolution:
I have a Category and Item relationship (Many-to-One) and I wanted to either select an existing item or create a new item.
In my Form class:
$builder->add('item', 'entity', array(
'label' => 'Item',
'class' => 'ExampleItemBundle:Item',
));
$builder->add('itemNew', new EmbedItemForm(), array(
'required' => FALSE,
'mapped' => FALSE,
'property_path' => 'item',
));
$builder->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (!empty($data['itemNew']['name'])) {
$form->remove('item');
$form->add('itemNew', new EmbedItemForm(), array(
'required' => TRUE,
'mapped' => TRUE,
'property_path' => 'item',
));
}
});
You can map two fields in a form to the same property using the property_path option. Then, using form events, use the submitted data to make a decision and modify the form so that only one of the fields has a mapped option that is true.
If I have understood, you want to create and store new clients in a Form "on fly", at the moment. I think that you have to do that using JavaScript and set an additional action in your controller.
JS -> Capture the event to add new client to you database (i.e. "Add new" button click event)
JS -> Inside this event, call via AJAX to your controller with the values of new client. (Using FOSJsRoutingBundle is easy to do)
Symfony2 -> Inside your new action, store the new client in your database.
JS -> OnSuccess event, in your AJAX call, add the new Client to your DropDownBox
(ddb.append(new element tag)
Just doing that you have your new client stored in the database and added to your dropdownbox
For my part i had the same kind of problem and i resolved it by creating 2 attribute in my formType;
For example, for you it would be:
customer->entity
new_customer-> collection
In your order entity file you will have to add 3 methods (getter, setter, and remover) getter and remover don't do anything but setter should call the setCustomer(c)
I'm not sure if it is the best way but it's the only way I figure it out!
The collection Form type allows to add and delete on the fly with allow_add and allow_delete attribute.
More informations by following these 2 links :
Official collection form field type reference
Cookbook about add and delete on the fly with collection type
If you don't like to get supplementary forms on the same page, you can integrate them in dialog boxes... But you definitely need a form to create new items...

How do I get a regular Checkbox in a Zend Form?

I have a form in Zend_Form that needs some checkboxes and I'd like them to be regular old checkboxes. You know, you give em a name and a value. If they are checked your post data contains name=>value.
Zend_Form is generating two inputs fields. One, the checkbox with a value=1 and the second a hidden input with a value=2. Both have the same name. I understand in theory how Zend expects the checkbox to work, but that's not how I expect it to work and it's not how I want it to work. How do I get my old fashion HTML checkbox back?
I have tried using $this->createElement, $this->addElement and creating a Zend_Form_Element_Checkbox manually. None allow me to set the checkbox's value and all generate the hidden input.
The final and REALLY correct answer is to add an option to the element :
$this->addElement('checkbox', 'my_element', array(
'label' => 'My Element Label',
'name' => 'my_element_name',
'disableHidden' => true
));
Zend_Form_Element_MultiCheckbox is what you're looking for.
The standard Checkbox element is meant to represent "yes/no" scenarios.
You could extend Zend library and add your own custom form element to render it just like you expect it. I did it for having a date field and it worked just fine.
I wonder why that does not work for you. You can set the values to anything you want (setCheckedValue() and setUncheckedValue()). So the only difference to normal checkbox is
if (null == $this->_getParam('checkbox', null)) {
//vs.
if ($unchecked == $this->_getParam('checkbox')) {
What exactly are you trying to do?