I have a simple ZF form that includes a hash element:
$hash = new Zend_Form_Element_Hash('hash');
$hash->setSalt('hf823hflw03j');
$hash->addErrorMessage('Form must not be resubmitted');
This works ok, but if I choose to strip out all the decorators and format the form using :
$this->setDecorators( array( array('ViewScript', array('viewScript' => '_form_register.phtml'))));
Then it seems that the hash value is renewed each time it is submitted and thus doesn't work.
In addition, PHPunit thinks the form element hash is invalid and so doesn't test the form processing.
Is there any solution to this?
Do you really need to use viewScript Decorator? Otherwise try to use this:
$this->setDecorators(array('ViewHelper','Errors'));
If you want to change the look of the Errors, you could create your own ErrorDecorator and then use it as follows:
$this->setDecorators(array('ViewHelper', new My_ErrorDecorator()));
Related
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...
In my form I create a checkbox
$form['existing_customer'] = array(
'#type' => 'checkbox',
'#title' => t('Are you an existing customer?')
);
When I validate it using hook_validate I would like to add a class to the label? Any ideas how to achieve this?
I can't imagine why you'd want to do this in a validation function, and I think there's a far easier way to accomplish what you're trying to do.
Each element in a Drupal form is wrapped with a container (which has an ID). Inside this container there will only ever be one label.
So if you need to target the element in CSS or JS you just need to do something like this:
#existing-customer-edit label {
// The rule
}
OR
$('#existing-customer-edit label').something();
If you really need to edit the label manually then you're going to have to provide a custom theme for that element, have a look at this example for more information (it's for Drupal 6 but the concept is the same in Drupal 7).
thanks Clive did a fairly nasty work around in the form validation function
$form_state['complete form']['myselectbox']['#title'] = '<span class="privacy-error">you did not check me</span>';
It ain't pretty but it works!
You can add a class in hook_validate():
$form_state['complete form']['submitted']['existing_customer']['#attributes']['class'][] = 'class_name';
I have a matrix of checkboxes which I am laying out in a table. I need to pull this matrix into a number of forms, and sometimes multiple times on one form, so I have set it up as a subform.
After much research and deliberation, I decided the best way to decorate the subform was using the viewScript decorator. The code for adding the subform to the form looks something like this:
$this->addSubForm(new Test_Form_Connection_Config_Base(), 'user');
$this->user->setDecorators(array(
array('viewScript', array('viewScript' => '_forms/userConfig.phtml')),
'Description',
'FieldSet',
));
For the most part this works fine however the one problem I have is that I can't get array notation to work. Obviously this becomes a problem when I include the matrix more than once on a particular form.
I tried using setIsArray(true) however this had no effefct. It seems that I need to run the FormElements decorator to get the array notation, but this then gives me a duplicate set of fields on the page (rendered once by FormElements, and once by viewScript).
I could manually construct the name of each element to reflect array notation, but this seems like the long way around. Are there any other options that I'm missing?
Thanks...!
Before using the ViewScript decorator, you should always use the PrepareElements decorator to normalize names.
See http://framework.zend.com/manual/en/zend.form.standardDecorators.html#zend.form.standardDecorators.prepareElements
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?
I have a search module. It has one form within it that produces the search field, I am using a viewScript that is stored within views/scripts/forms to render the form.
I want this form to appear on ever screen so I have written a ViewHelper that creates the from and returns it. This works fine when I am within the search module but when I am in any other module I am getting an error.
Any ideas why?
This is what is used to create the viewScript in the form
$this->setDecorators(array(
array( 'ViewScript', array('viewScript' => 'forms/Search.phtml'))
));
Thanks,
Martin
In my code I have to put a / in front of the path so for you it would mean:
$this->setDecorators(array(
array( 'ViewScript', array('viewScript' => '/forms/Search.phtml'))
));