I am having some problems working out how to use custom forms in Zend Framework.
I have followed various guides but none seem to work. Nothing at all gets rendered.
Here is the bits of code that I am trying to use (All code below is in the default module). I have simplified the code to a single input for the test.
applications/forms/One/Nametest.php
class Application_Form_One_Nametest extends Zend_Form {
public function init() {
$this->setMethod('post');
$name = new Zend_Form_Element_Text('name');
$name->setLabel('Box Name')
->setRequired(true)
->addFilter('StripTags')
->addFilter('StringTrim')
->addValidator('NotEmpty');
$submit = new Zend_Form_Element_Submit('submit');
$submit->setLabel('Submit Message');
$submit->setAttrib('id', 'submitbutton');
$submit->setAttrib('class', 'bluebutton');
$this->addElements(array($name, $submit));
}
}
application/views/scripts/one/formlayout.phtml
<form action="<?= $this->escape($this->form->getAction()) ?>" method="<?= $this->escape($this->form->getMethod()) ?>">
<p>
Please provide us the following information so we can know more about
you.
</p>
<? echo $this->element->name ?>
<? echo $this->element->submit ?>
</form>
application/controllers/IndexController.php
public function formtestAction() {
$form = new Application_Form_One_Nametest();
$form->setDecorators(array(array('ViewScript', array('viewScript' => 'one/formlayout.phtml'))));
$this->view->form = $form;
}
application/views/scripts/index/formtest.phtml
<h1>Formtest</h1>
<?
echo $this->form;
?>
The above code does not throw any errors or render any part of formlayout.phtml including the form tags or text between the p tags.
Can anybody tell me what I might be doing wrong?
I think the problem is your form element's decorator. You should set the decorator to ViewHelper and Error only. It works for me at least.
Here is the code I used and it should work
applications/forms/Form.php
class Application_Form_Form extends Zend_Form {
public function loadDefaultDecorators() {
$this->setDecorators(
array(
array(
'ViewScript',
array(
'viewScript' => 'index/formlayout.phtml',
)
)
)
);
}
public function init() {
$this->setAction('/action');
$this->setMethod('post');
$this->addElement('text', 'name', array(
'decorators' => array('ViewHelper', 'Errors')
));
}
}
application/views/scripts/index/formlayout.phtml
<form action="<?php echo $this->element->getAction(); ?>" method="<?php echo $this->element->getMethod(); ?>">
<div>
<label for="name">Box Name</label>
<?php echo $this->element->name; ?>
</div>
<input type="submit" value="Submit Message" id="submitbutton" class="bluebutton">
</form>
application/views/scripts/index/index.phtml
<!-- application/views/scripts/index/index.phtml -->
<?php echo $this -> form; ?>
application/controllers/IndexController.php
public function indexAction() {
$form = new Application_Form_Form();
$this -> view -> form = $form;
}
Here is a very simple example to get you going adapted from this article.
The form:-
class Application_Form_Test extends Zend_Form
{
public function init()
{
$this->setMethod('POST');
$this->setAction('/');
$text = new Zend_Form_Element_Text('testText');
$submit = new Zend_Form_Element_Submit('submit');
$this->setDecorators(
array(
array('ViewScript', array('viewScript' => '_form_test.phtml'))
)
);
$this->addElements(array($text, $submit));
$this->setElementDecorators(array('ViewHelper'));
}
}
The order in which setDecorators(), addElements() and setElementDecorators() are called is very important here.
The view script _form_test.phtml can be called anything you like, but it needs to be in /views/scripts so that it can be found by the renderer.
/views/scripts/_form_test.phtml would look something like this:-
<form id="contact" action="<?php echo $this->element->getAction(); ?>"
method="<?php echo $this->element->getMethod(); ?>">
<p>
Text<br />
<?php echo $this->element->testText; ?>
</p>
<p>
<?php echo $this->element->submit ?>
</p>
</form>
You instantiate the form, pass it to the view and render it as usual. The output from this example looks like this:-
<form id='contact' action='/' method='post'>
<p>
Text<br />
<input type="text" name="testText" id="testText" value=""></p>
<p>
<input type="submit" name="submit" id="submit" value="submit"></p>
</form>
That should be enough to get you started creating your own forms.
Usually, if you don't see anything on the screen it means that some sort of error happened.
Maybe you have errors turned off or something, maybe not. I'm just trying to give you ideas.
The only things I could spot where the following.
In the below code, you have to still specify the form when trying to print out the elements.
<form>
action="<?php $this->escape($this->element->getAction()) ?>"
method="<?php $this->escape($this->element->getMethod()) ?>" >
<p>
Please provide us the following information so we can know more about
you.
</p>
<?php echo $this->element->getElement( 'name' ); ?>
<?php echo $this->element->getElement( 'submit' ) ?>
</form>
As vascowhite's code shows, once you are inside the viewscript, the variable with the form is called element. The viewscript decorator uses a partial to do the rendering and thus it creates its own scope within the viewscript with different variable names.
So, although in your original view it was called $form, in the viewscript you'll have to call it element.
Also, maybe it was copy/paste haste, but you used <? ?> tags instead of <?= ?> or <?php ?> tags. Maybe that caused some error that is beyond parsing and that's why you got no output.
Related
I'm a bit confused with designing forms in zend.
I understood that I have the fields in my form class and the look should be done in the views.
In the index view which is nearly plain html I don't have problems, but in the add and edit views which show my form I have problems to change the look.
I have a viewscript like follows:
<?php
$title = 'AVB ändern';
$this->headTitle($title);
?>
<h1><?= $this->escapeHtml($title) ?></h1>
<?php
$id= $form->get('id');
$id->setAttribute('class', 'form-control');
$id->setAttribute('placeholder', 'id');
$avbname= $form->get('avbname');
$avbname->setAttribute('class', 'form-control');
$avbname->setAttribute('placeholder', 'avbname');
$vbedingungen= $form->get('vbedingungen');
$vbedingungen->setAttribute('class', 'form-control');
$vbedingungen->setAttribute('placeholder', 'vbedingungen');
$versichererid= $form->get('versichererid');
$versichererid->setAttribute('class', 'form-control');
$versichererid->setAttribute('placeholder', 'versichererid');
$aktiv= $form->get('aktiv');
$aktiv->setAttribute('class', 'form-control');
$aktiv->setAttribute('placeholder', 'aktiv');
$submit = $form->get('submit');
$submit->setAttribute('class', 'btn btn-primary');
$form->prepare();
echo $this->form()->openTag($form);
?>
<div class="form-group">
<?= $this->formElement($id) ?>
<?= $this->formElementErrors()->render($id, ['class' => 'help-block']) ?>
</div>
<div class="form-group">
<?= $this->formLabel($avbname) ?>
<?= $this->formElement($avbname) ?>
<?= $this->formElementErrors()->render($avbname, ['class' => 'help-block']) ?>
</div>
<div class="form-group">
<?= $this->formLabel($vbedingungen) ?>
<?= $this->formElement($vbedingungen) ?>
<?= $this->formElementErrors()->render($vbedingungen, ['class' => 'help-block']) ?>
</div>
<div class="form-group">
<?= $this->formLabel($versichererid) ?>
<?= $this->formElement($versichererid) ?>
<?= $this->formElementErrors()->render($versichererid, ['class' => 'help-block']) ?>
</div>
<div class="form-group">
<?= $this->formLabel($aktiv) ?>
<?= $this->formElement($aktiv) ?>
<?= $this->formElementErrors()->render($aktiv, s['class' => 'help-block']) ?>
</div>
<?php
echo $this->formSubmit($submit);
echo $this->formHidden($form->get('id'));
$form->setAttribute('action', $this->url('typavb', ['action' => 'edit']));
echo $this->form()->closeTag();
Of course it shows one field beneath the other.
How can I show two fields in a row (with the labels) ?
I really would appreciate an example or a tip to a good tutorial, which shows how to do it properly with this zend3 concept.
Is it even the right place to do it in the view or do I need a new layout.phtml for this case?
To print parts of Elements separately, there's several functions pre-defined in ZF. You can find all of them in \Zend\Form\ConfigProvider->getViewHelperConfig(), see here on Github.
In your case, your already using formLabel, formElement and formElementErrors.
These are handy for separte use if you have something like Currency, where you'd like a user to both fill in an amount and choose a currency but only use a single label, e.g.:
$this->formLabel($form->get('amount'));
$this->formElement($form->get('amount'));
$this->formElementErrors($form->get('amount'));
$this->formElement($form->get('currency'));
$this->formElementErrors($form->get('currency'));
An entire "form row" is made up out of:
A label (optional)
Element
ElementErrors (if present after server-side validation)
So, as in this example you need the entire "amount" bit, you could shorten the above to:
$this->formRow($form->get('amount')); // prints all elements for the row
$this->formElement($form->get('currency'));
$this->formElementErrors($form->get('currency'));
If you look closely through the linked ConfigProvider of 'zendframework/zend-form', you might've noticed there's also a form ViewHelper. This can be used to print an entire form in a single go, like so:
file: add-foo.phtml
<?= $this->form($form) ?>
And that's it. It prints the whole form. Of course it uses the ZF defined ViewHelpers, as such also with that layout and classes applied.
If you wish, can take that config and override it in your own projects.
For example, your question code shows you add <div class="form-group"></div> around each row. Presumably for Bootstrap 4. To do this magically so you need not do:
<div class="form-group">
<?= $this->formRow($form->get('foo')) ?>
</div>
We can adjust the formRow ViewHelper. Simply follow these steps:
Create a FormRow.php in your own project, e.g. module/Foo/src/View/Helper/FormRow.phtml
Make sure to extend it from ZF's FormRow and copy in the original (ZF) render function, like so:
use Zend\Form\View\Helper\FormRow as ZendFormRow;
class FormRow extends ZendFormRow
{
public function render(ElementInterface $element, $labelPosition = null)
{
// its content
}
}
We want to add a wrapper (form-group class div), so define it in the class, like so:
class FormRow extends ZendFormRow
{
protected $inputRow = '<div class="form-group">%s</div>';
// the other stuff
}
At the bottom of the render function, you'll find the following code (before the else):
if ($this->renderErrors) {
$markup .= $elementErrors;
}
Place after the above:
$markup = sprintf(
$this->inputRow,
$markup,
);
Register your new ViewHelper, using the same aliases as ZF so as to overwrite the values:
'view_helpers' => [
'aliases' => [
'formrow' => FormRow::class,
'form_row' => FormRow::class,
'formRow' => FormRow::class,
'FormRow' => FormRow::class,
],
'factories' => [
FormRow::class => InvokableFactory::class,
],
],
Done.
Now when you do $this->form($form) the FormElement ViewHelper from ZendFramework will receive your custom formRow ViewHelper when it its Factory does ->get('formRow'), as the config is overwritten to your own. As such, all rows will now automagically have the surrounding div.
Bit more than you asked for, but have fun ;) I'm gonna stop avoiding work now O:)
When I submit my form i got some errors,
This is my form script which contains posted fields.
<?php $form = ActiveForm::begin([
'action'=>'userpermission/create',
]); ?>
<form method="post" action="<?php echo Yii::$app->getUrlManager()->createUrl('admin/userpermission/create')?>">
<ul class="list-unstyled">
<li>
<?= $form->field($model, 'idPermission')->checkboxList(ArrayHelper::map(Permission::find()->all(),"idPermission", "libelle", [
'onclick' => "$(this).val( $('input:checkbox:checked').val());",
'item' => function($index, $label, $name, $checked, $value) {
return "<label class='ckbox ckbox-primary col-md-4'><input type='checkbox' {$checked} name='{$name}' value='{$value}' tabindex='3'>{$label}</label>";
}
])) ?>
</li><br>
</ul>
<div class="form-group">
<?php Html::submitButton($model->isNewRecord ? 'Valider' : 'Create' ,['class' => $model->isNewRecord ? 'btn btn-primary','value'=>'Create', 'name'=>'submit']) ?>
</div>
<?php ActiveForm::end(); ?>
and my create function looks like but i got the error undefined variable model!
public function actionCreate()
{
$model = new Userpermission();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
print_r(Yii::$app->request->post());
exit;
return $this->redirect(['index', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
1st off, you dont need that <form> tag.
<?php $form = ActiveForm::begin([
'action'=>'userpermission/create',
]); ?>
creates and initializes the form for you with corresponding client-validations.
the possible issue is due to unclosed </form> which anyways is unnecessary.
suggesting to remove the <form> tag entirely. and try again and if any issue please let me know the error.
also bring the print_r(Yii::$app->request->post()); before if condition.
enable error reporting in your function
error_reporting(E_ALL);
please give the filename to code block. it would be easier to understand that way.
in my EditController I have indexAction :
public function indexAction()
{
$delete = new DeleteForm();
$view = new ViewModel(array('delete' => $delete ));
return $view;
}
and the view
<?php
$formDelete = $this->delete;
$formDelete->prepare();
$formDelete->setAttribute('action', $this->url(NULL, array('controller'=>'Register', 'action' => 'process')));
?>
<?php echo $this->form()->openTag($formDelete);?>
<div class="form-group">
<?=$this->formLabel($formDelete->get('reason')); ?>
<?=$this->formElement($formDelete->get('reason'))?>
<?=$this->formElementErrors($formDelete->get('reason'))?>
</div>
<div class="form-group">
<?=$this->formElement($formDelete->get('delete-button'))?>
</div>
<?php echo $this->form()->closeTag();?>
Despite I have action attribute set to RegisterController and processAction in page source I see always the same action. In setAttribute $this->url I can type whatever I want, in the code source always is
<form method="post" name="deleteForm" enctype="multipart/formdata" action="/App/public/element/edit" id="deleteForm">
The first parameter of the URL helper should be the name of the route you want to use, not NULL. By using NULL, ZF will fall back on using the current route, which I'd guess is not correct in your case.
I am using Symfony 1.4, and am using embedded forms to place multiple similar forms into one form for a configuration page. I am having success showing the form, but the default values of the sfWidgetFormChoice widgets are not being rendered, i.e. the selected="selected" attribute is gone from the HTML.
Incidentally, the default values show up if I don't use embedded forms. The problem with avoiding embedded forms is that each form has identical inputs and therefore overwrites itself.
The action code is as such, some code omitted for brevity:
$serviceFormArray = array();
$this->fullForm = new ConfigForm();
foreach($this->serviceArray as $net => $service)
{
$this->partialForm = new ConfigForm();
foreach($service as $typeId => $val)
{
$typeObj = Doctrine::getTable('Type')->find($typeId);
$typeField = new sfWidgetFormChoice(array(
'default' => $val,
'choices' => array('1' => 'on', '0' => 'off'),
'label' => $typeObj->name)
);
$typeField->setDefault($val);
$serviceFormArray[$typeObj->name] = $typeField;
}
$netObj = Doctrine::getTable('Network')->find($net);
$this->partialForm->setWidgets($serviceFormArray);
$this->fullForm->embedForm($netObj->name,$this->partialForm);
}
and the template looks like this, some code omitted for brevity:
<div class="sectionBox">
<?php echo $fullForm->renderFormTag('/configure/submitconfig') ?>
<?php foreach ($fullForm->getVisibleFields() as $part => $field): ?>
<div class="settingsField">
<?php echo $field->renderLabel() ?>
<?php echo $field->render() ?>
<input type="hidden" name="plug" value="<?php echo $plugName; ?>"/>
</div>
<?php endforeach; ?>
<div id="submitConfig"><input type="submit" value="Save"/></div>
</form>
</div>
Try setting default value via $form->setDefault($name, $default).
$this->partialForm->setDefault($typeObj->name, $val);
How can I change the template of a form in sfDoctrineGuardPlugin?
That is, I need to change the HTML (class, id) of the input elements (username, password) of a login form provided by sfDoctrineGuardPlugin.
I've changed apps/app_name/modules/sfGuardAuth/templates/singinSuccess.php, but it then just echoes $form (I need to change contents of that part - $form):
<form action="<?php echo url_for('#sf_guard_signin') ?>" method="post">
<table>
<?php echo $form ?>
</table>
<input type="submit" class="go_button" value="ir" />
<?php echo __('Forgot your password?') ?>
</form>
(It really should be something like changing a _form.php => I can't find this, though :S)
Thank you all for any answers provided =)
In the sign in form class (forget it's name), there will be something like:
'username' => new sfWidgetFormInput(array(), array())
Modify that to:
'username' => new sfWidgetFormInput(array(), array('id' => 'jibbly', 'class' => 'wibbly'))