i have this in RcProfileTableForm.class.php
abstract class BaseRcProfileTableForm extends BaseFormPropel
{
public function setup()
{
$this->setWidgets(array(
'id' => new sfWidgetFormInputHidden(),
'created_at' => new sfWidgetFormDateTime(),
'name' => new sfWidgetFormInputText(),
'password' => new sfWidgetFormInputText(),
'unique_code' => new sfWidgetFormInputText(),
'msisdn' => new sfWidgetFormInputText(),
'profile_pic' => new sfWidgetFormInputText(),
'email' => new sfWidgetFormInputText(),
'age' => new sfWidgetFormInputText(),
)
}
and the form gets called like this:
<?php
include_partial('form', array('form' => $form));
echo $form->renderGlobalErrors(); ?>
so on the actual page it displays the label and the inputbox
what i need to do now is add a "*" to the end of the inputboxes of msisdn and email
the * will denote to a message appropriate to these fields
how can i achieve this? there is nowhere html that i can add a to this because the whole form gets called from the widgets
any advice please?
thanks
In your form (RcProfileTableForm) you can add custom label
class RcProfileTableForm extends BaseRcProfileTableForm
{
public function configure()
{
$this->widgetSchema->setLabels(array(
'email' => 'email*',
}
// If you want to customize widget you can make:
$this->widgetSchema['email'] = new sfWidgetFormInputText(array(), array("style"=>'width: 290px;'));
));
// UPADATE
Read this
So you must customize your form partial in apps/frontend/yourmodules/template/_form.php
In _form.php I think you have now something like this:
You can make :
<?php echo $form['email']->renderError(); ?>
<?php echo $form['email']->render() ?> <?php echo __("Email*"); ?>
//or
<?php echo $form['email']->render() ?> $form['email']->renderLabel() ?>
Related
I am using the great bundle https://github.com/misd-service-development/phone-number-bundle to store and retrieve phone number, but I have a problem when I want to pre-fill a form with it (not the same entity).
I have the following code in my Type
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use libphonenumber\PhoneNumberFormat;
use Misd\PhoneNumberBundle\Form\Type\PhoneNumberType;
class CreateAdType extends AbstractType
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
//Builds the form
public function buildForm(FormBuilderInterface $builder, array $options)
{
//Defines data
$user = $this->tokenStorage->getToken()->getUser();
$userEmail = is_object($user) ? $user->getEmail() : '';
$userPhone = is_object($user) ? $user->getPhone() : '';
//Defines fields
$builder
->add('phone', PhoneNumberType::class, array(
'label' => 'label.phone',
'disabled' => $disabled,
'widget' => PhoneNumberType::WIDGET_COUNTRY_CHOICE,
'country_choices' => array(
'FR',
),
))
->add('email', EmailType::class, array(
'label' => 'label.email',
'disabled' => $disabled,
'required' => true,
'attr' => array(
'placeholder' => 'placeholder.email',
'value' => $userEmail,
)))
;
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
$view['phone']->children['number']->vars['data'] = '123456789';
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Ad',
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
// a unique key to help generate the secret token
'intention' => 'createAdForm',
));
}
public function getName()
{
return 'createAd';
}
}
The resulting html code is the following
<div class="form-group">
<label>Phone</label>
<div>
<div id="create_ad_phone" value="**THE_VALUE_APPEARS_HERE**">
<select id="create_ad_phone_country" name="create_ad[phone][country]">
<option value="FR" >France (+33)</option>
</select>
<input type="text" id="create_ad_phone_number" name="create_ad[phone][number]" value="**BUT_I_NEED_THE_VALUE_HERE**" />
</div>
</div>
</div>
This sets the value to the phone div, but not to the input phone_number, where I need it. Is there a way ?
Following in your form type, don't forget to use
...
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
...
public function finishView(FormView $view, FormInterface $form, array $options)
{
$view['phone']->children['number']->vars['value'] = $view['phone']->children['number']->vars['value'] ? $view['phone']->children['number']->vars['value'] : '+13008228232';
}
In you method add you can use choices for select
$builder
->add('phone', PhoneNumberType::class, array(
'widget' => PhoneNumberType::WIDGET_COUNTRY_CHOICE,
'country_choices' => array(
'FR',
),
'choices' => array('number' => $user->getPhone))
);
Are you rendering in twig template?
If so have you tried passing in "$user" object to twig template from controller, and then call the "getPhone" function in twig.
Like so, in your controller:
return $this->render('default/some_template.html.twig', array(
'form' => $form->createView(),
'user' => $user,
));
Then in your twig template somewhere:
{{ form_widget(form.phone, {'value' : user.getPhone}) }}
Try something like that to see if it works.
I haven't tried this - but it might work.
I'm trying to create a menu bar from a template in my view helper with Zend\Navigation.
I'm getting a little closer and edited this thread with code I have now.
Here is the view helper:
<?php
namespace Helpdesk\View\Helper;
use Zend\View\Helper\AbstractHelper;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class Navbar extends AbstractHelper implements ServiceLocatorAwareInterface {
public function setServiceLocator(ServiceLocatorInterface $serviceLocator) {
$this->serviceLocator = $serviceLocator;
return $this;
}
public function getServiceLocator() {
return $this->serviceLocator;
}
public function __invoke() {
$partial = array('helpdesk/helpdesk/subNavTest.phtml','default');
$navigation = $this->getServiceLocator()->get('navigation');
$navigation->menu()->setPartial($partial);
return $navigation->menu()->render();
}
}
I configured the navigation in module.config.php like so:
'view_helpers' => array(
'invokables' => array(
'navbar' => 'Helpdesk\View\Helper\Navbar',
),
),
'navigation' => array(
'default' => array(
array(
'label' => 'One',
'route' => 'link',
),
array(
'label' => 'Two',
'route' => 'link',
),
array(
'label' => 'Three',
'route' => 'link',
), ...
But when I display it in my view like this <?php echo $this->navbar(); ?> it just displays the partial template without the navigation config from module.config.php.
If I do the following right in my view it displays fine with the config that I set:
<?php $partial = array('helpdesk/helpdesk/subNavTest.phtml','default') ?>
<?php $this->navigation('navigation')->menu()->setPartial($partial) ?>
<?php echo $this->navigation('navigation')->menu()->render() ?>
Why isn't my view helper pulling in the navigation config?
If I do the following right in my view it displays fine with the config that I set:
Yes, that's because in your view (the code that works), you're telling the navigation helper to use a menu container called navigation at this line...
<?php $this->navigation('navigation')->menu()->setPartial($partial) ?>
^^^^^^^^^^- This is the menu container
In your navbar helper, you don't specify a menu container. If you haven't already used the navigation helper at that point it has no menu, and creates an empty one.
You have two choices, either tell the navigation helper which container to use before calling your helper
// set the menu
<$php $this->navigation('navigation'); ?>
// render helper
<?php echo $this->navbar(); ?>
or, have your helper accept a parameter in its __invoke method which it can pass to the helper
public function __invoke($container) {
$partial = array('helpdesk/helpdesk/subNavTest.phtml','default');
$navigation = $this->getServiceLocator()->get('navigation');
// tell navigation which container to use
$navigation($container)->menu()->setPartial($partial);
return $navigation->menu()->render();
}
and call it in your view as
<?php echo $this->navbar('navigation'); ?>
I want to put a dropdown in my project which is made in zf2... I wasted all day but I only got a static dropdown, not dynamic. Can anyone help me with this problem??
UserForm.php
$this->add(array(
'name' => 'group_name',
'type' => 'select',
'attributes' => array(
'id'=>'group_name',
'class'=>'large',
'options' => array('1=>php','2'=>'java'),
),
'options' => array(
'label' => '',
),
));
Thanks in advance for your valuabe answer.
Try this:
$this->add(array(
'name' => 'group_name',
'type' => 'select',
'attributes' => array(
'id'=>'group_name',
'class'=>'large',
),
'options' => array(
'label' => '',
'value_options' => array(
'1' => 'php',
'2' => 'java'
),
),
));
This is what i did:
In my constructor for my form
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'color',
'options' => array(
'empty_option' => 'Select a Color',
'value_options' => self::getColors(),
'label' => 'Color',
),
));
In the form class yet, i created this method:
public static function getColors() {
// access database here
//example return
return array(
'blue' => 'Blue',
'red' => 'Red',
);
}
In my view script:
<div class="form_element">
<?php $element = $form->get('color'); ?>
<label>
<?php echo $element->getOption('label'); ?>
</label>
<?php echo $this->formSelect($element); ?>
</div>
Think about it from a abstract level.
You have one Form
The Form needs Data from the outside
So ultimately your Form has a Dependency. Since we've learned from the official docs, there's two types of Dependency-Injection aka DI. Setter-Injection and Constructor-Injection. Personally(!) i use one or the other in those cases:
Constructor-Injection if the dependency is an absolute requirement for the functionality to work
Setter-Injection if the dependencies are more or less optional to extend already working stuff
In the case of your Form, it is a required dependency (because without it there is no populated Select-Element) hence i'll be giving you an example for Constructor-Injection.
Some action of your controller:
$sl = $this->getServiceLocator();
$dbA = $sl->get('Zend\Db\Adapter\Adapter');
$form = new SomeForm($dbA);
That's all for the form. The population now happens inside your Form. This is only an example and may need some fine-tuning, but you'll get the idea:
class SomeForm extends \Zend\Form
{
public function __construct(\Zend\Db\Adapter\Adapter $dbA)
{
parent::__construct('my-form-name');
// Create all the form elements and stuff
// Get Population data
$popData = array();
$result = $dbA->query('SELECT id, title FROM Categories', $dbA::QUERY_MODE_EXECUTE)->toArray();
foreach ($result as $cat) {
$popData[$cat['id'] = $cat['title'];
}
$selectElement = $this->getElement('select-element-name');
$selectElement->setValueOptions($popData);
}
}
Important: I HAVE NO CLUE ABOUT Zend\Db the above code is only for how i think it would work going by the docs! This is the part that would need some optimization probably. But all in all you'll get the idea of how it's done.
In your controller you can do something like below;
On my first example assuming that you have a Group Table. Then we're going to fetchAll the data in group table;
We need the id and name to be display in select options;
public function indexAction()
{
$groupTable = new GroupTable();
$groupList = $groupTable->fetchAll();
$groups = array();
foreach ($groupList as $list) {
$groups[$list->getId()] = $list->getName();
}
$form = new UserForm();
$form->get('group_name')->setAttributes(array(
'options' => $groups,
));
}
OR
in this example the grouplist is hardcoded;
public function indexAction()
{
$groupList = array('1' => 'PHP', '2' => 'JAVA', '3' => 'C#');
$groups = array();
foreach ($groupList as $id => $list) {
$groups[$id] = $list;
}
$form = new UserForm();
$form->get('group_name')->setAttributes(array(
'options' => $groups,
));
}
Then in your view script;
<?php
$form = $this->form;
echo $this->formRow($form->get('group_name'));
?>
Or you can right a controller helper, you may check this link http://www.resourcemode.com/me/?p=327
Just came across the same problem and had to take a look into zf2 source.
Here's a more OOP solution:
Inside the form constructor:
$this->add(array(
'name' => 'customer',
'type' => 'Zend\Form\Element\Select',
'attributes' => array(
'options' => array(
0 => 'Kunde',
)
),
'options' => array(
'label' => 'Kunde'
)));
inside the controller:
$view->form = new SearchForm();
$customers = $view->form->get('customer')->getValueOptions();
$customers[] = 'Kunde1';
$customers[] = 'Kunde2';
$customers[] = 'Kunde3';
$customers[] = 'Kunde4';
$view->form->get('customer')->setValueOptions($customers);
I'm trying to set a drop down to 'required' but the form still goes through. What am I doing wrong?
Here is the code:
this->exportForm = new sfForm();
$widgets['sheet_type'] = new sfWidgetFormDoctrineChoice(array('model' => 'ExportSheet', 'add_empty' => true));
$this->exportForm->setWidgets($widgets);
$this->exportForm->setValidators(array('sheet_type' => new sfValidatorDoctrineChoice(array('model' => 'ExportSheet', 'required' => true), array('required' => 'Please select a sheet type to export.') )));
UPDATE:
I've made the changes suggested.
actions.class.php:
$this->exportForm = new sfForm();
$this->exportForm->getWidgetSchema()->setNameFormat('exportForm[%s]');
$widgets['sheet_type'] = new sfWidgetFormDoctrineChoice(array('model' => 'ExportSheet', 'add_empty' => true));
$this->exportForm->setWidgets($widgets);
$this->exportForm->setValidators(array('sheet_type' => new sfValidatorDoctrineChoice(array('model' => 'ExportSheet', 'required' => true), array('required' => 'Please select a sheet type to export.') )));
if ($request->isMethod('post'))
{
$this->exportForm->bind($request->getParameter('exportForm'));
if ($this->exportForm->isValid())
{
...
}
}
Template:
<form method="post" action="<?php echo url_for('#export'); ?>">
<div id="export" style="display: block">
<?php echo $exportForm['sheet_type']->renderRow(); ?>
</form>
I can see when I submit that the echoing $request->getParameter('sheet_type') does return a value. If this is the case, why is the validation still failing?
There are 2 parts to validating a form ... the first is adding the validators the second is checking if its valid ....
take this example :
public function executeSomeaction(sfWebRequest $request)
{
// Define the form
this->exportForm = new sfForm();
$widgets['sheet_type'] = new sfWidgetFormDoctrineChoice(array('model' => 'ExportSheet', 'add_empty' => true));
$this->exportForm->setWidgets($widgets);
$this->exportForm->setValidators(array('sheet_type' => new sfValidatorDoctrineChoice(array('model' => 'ExportSheet', 'required' => true), array('required' => 'Please select a sheet type to export.') )));
// Deal with the request
if ($request->isMethod('post'))
{
$this->exportForm->bind($request->getParameter(<your form>));
if ($this->exporForm->isValid())
{
// Handle the form submission
// ...
$this->redirect('foo/bar');
}
}
}
Its only the second part within if ($request->isMethod('post')) that applies your validation and checks the user submitted data. See here in the symfony docs about handling forms with validation
If you use the following to add a naming schema for your form output then getting all of the results is easy ....
$this->exportForm->getWidgetSchema()->setNameFormat('exportForm[%s]');
then you can get use :
$this->exportForm->bind($request->getParameter('exportForm'));
this will then get the array with all of the field values in it and bind it to your form - ready for checking to see if its valid.
Update
you need to specify
$this->exportForm->getWidgetSchema()->setNameFormat('exportForm[%s]');
after
$this->exportForm->setWidgets($widgets);
as the setWidgets method resets the naming format
I'm building a simple form mailer in symfony using sfExtraForm plugin captcha. Everything works except sfValidator is not redirecting the user and showing an error when any field is invalid. The only thing I can think of is I did not generate the module. I built it from scratch.
I have to do the redirect manually. Is this because this is a sfForm and not an sfDoctrine Form? It is if the line if ($form->isValid()) returns false but without the associated redirect and error codes. Here is the program. Thanks:
Form:
<?php
class AdsForm extends sfForm
{
public function configure()
{
$this->setWidgets(array(
'name' => new sfWidgetFormInputText(),
'email' => new sfWidgetFormInputText(),
'phone' => new sfWidgetFormInputText(),
'fax' => new sfWidgetFormInputText(),
'attention' => new sfWidgetFormInputText(),
'message' => new sfWidgetFormInputText(),
'captcha' => new sfWidgetFormReCaptcha( array('public_key'=>self::PUBLIC_KEY)),
));
$this->widgetSchema->setNameFormat('ads[%s]');
$this->setValidators(array(
'name' => new sfValidatorString(array('max_length' => 50)),
'email' => new sfValidatorString(array('max_length' => 50)),
'phone' => new sfValidatorString(array('max_length' => 50)),
'fax' => new sfValidatorString(array('max_length' => 50)),
'attention' => new sfValidatorString(array('max_length' => 50)),
'message' => new sfValidatorString(array('max_length' => 255)),
'captcha' => new sfValidatorReCaptcha(array('private_key' => self::PRIVATE_KEY))
));
$this->widgetSchema->setLabels(array(
'name' => 'Your Name:*',
'email' => 'Your Email:*',
'phone' => 'Your Phone:*',
'fax' => 'Your Fax',
'attention' => 'Attention:*',
'message' => 'Mail Message:*',
'captcha' => 'Image Verification:*',
));
}
}
Action:
class adsActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
$this->form=new adsForm();
}
public function executeSend(sfWebRequest $request){
$this->forward404Unless($request->isMethod(sfRequest::POST));
$form=new adsForm();
$captcha = array('recaptcha_challenge_field' => $request->getParameter('recaptcha_challenge_field'),'recaptcha_response_field' => $request->getParameter('recaptcha_response_field'),);
$form->bind(array_merge($request->getParameter('ads'), array('captcha' => $captcha)));
if ($form->isValid())
{
print_r($_REQUEST);
$ads=$this->getRequestParameter('ads');
print_r($ads);
$headers = 'From: '."\r\n" .
'Reply-To: no-reply#yellowexplorer.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
//mail(' ******#yahoo.com','Yellow Explorer','An account has been created for you at yellowexplorer.com with a username of '.$this->username.'. Please click here to finish creating your account.',$headers);
}
else{
$this->redirect('/ads');
}
}
}
You're not seeing any errors because you're redirecting! To render form fields with their errors, you need to be rendering the actual form instance that you called bind on. Try changing $this->redirect('/ads') to $this->setTemplate('index').
Other potential changes (outside the scope of the question):
You can enforce the request method requirements of the send action at the routing level. Make the send route an sfRequestRoute and add the requirement { sf_method: post }.
Symfony has a built in mailer, sfMailer. Any reason you've decided not to use it?