KnpMenuBundle and the proposed tutorial example: is something wrong? - symfony

The KNP MenuBundle is a Symfony2 bundle for handling menus in a very dynamic way. The bundle comes out with a simple tutorial example, provided here.
In the proposed example, within the Builder class, the authors supposed that a function setCurrentUri() has to be called on the $menu object. However, $menu is an instance of MenuItem class, which does not implements the above mentioned function.
To make the answer self contained, I report the code of the example class provided here:
<?php
// src/Acme/DemoBundle/Menu/Builder.php
namespace Acme\DemoBundle\Menu;
use Knp\Menu\FactoryInterface;
use Symfony\Component\DependencyInjection\ContainerAware;
class Builder extends ContainerAware
{
public function mainMenu(FactoryInterface $factory, array $options)
{
$menu = $factory->createItem('root');
$menu->setCurrentUri($this->container->get('request')->getRequestUri());
$menu->addChild('Home', array('route' => 'homepage'));
$menu->addChild('About Me', array(
'route' => 'page_show',
'routeParameters' => array('id' => 42)
));
// ... add more children
return $menu;
}
}
PS: Notice that an important import is missing in this example, which I report in the following for sake of completeness:
use Symfony\Component\HttpFoundation\Request;

I am also looking for the documentation update, but as a temporary solution you can set versions in deps like these:
[KnpMenu]
git=https://github.com/KnpLabs/KnpMenu.git
version=v1.1.2
[KnpMenuBundle]
git=https://github.com/KnpLabs/KnpMenuBundle.git
target=/bundles/Knp/Bundle/MenuBundle
version=v1.1.0

Related

Symfony 2.8 - how to create "terms & conditions" check-box which isn't mapped to the underlying model

I'm using Symfony 2.8 and I'm trying to create a registration form containing a "terms & conditions" check-box which isn't mapped to the underlying data model.
I've followed this cookbook article:
How to Implement a Simple Registration Form
Everything in the form validation works, except for the the "terms & conditions" check-box. After submitting the form, the check-box validation doesn't get triggered.
This is my code:
namespace Likestripe\AdminBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use Symfony\Component\Validator\Constraints\IsFalse;
use Symfony\Component\Validator\Constraints\IsTrue;
class RegistrationFormType extends AbstractType { //BaseType
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
// call parent constructor
//parent::buildForm($builder, $options);
// add your custom fields
$builder->add('salutation', ChoiceType::class, array('choices' => array('Herr' => 0, 'Frau' => 1), 'choices_as_values' => true));
$builder->add('firstname', TextType::class, array());
$builder->add('lastname', TextType::class, array());
$builder->remove('username');
$builder->add('company', new CompanyFormType());
$builder->add('conditions', CheckboxType::class, array('mapped' => false, 'constraints' => new IsTrue(array("message" => "Bitte akzeptieren Sie noch die AGB und Nutzungsbedingungen."))));
$builder->add('submit', SubmitType::class, array('label' => 'Registrieren'));
} // end function
public function getParent() {
return 'FOS\UserBundle\Form\Type\RegistrationFormType';
// Or for Symfony < 2.8
// return 'fos_user_registration';
}
/**
* function deprecated since 2.8 https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#form
*
* #return string
*/
public function getName() {
//return 'likestripe_user_registration';
return $this->getBlockPrefix();
} // end function
public function getBlockPrefix() {
return 'likestripe_user_registration';
}
} // end class
I can't see any difference between my code and the code demonstrated in the cookbook article.
Screen capture of my Symfony debug console:
UPDATE:
As Kamil proposed, I've checked if the 'conditions' check-box form parameter gets posted after submitting the form.
The param gets posted als long as the check-box is checked, but if not, the "conditions" form parameter doesn't get posted at all... this behavior reminds me of this case.
I'm still wondering why the official Symfony documentation proposes a isTrue Validator which doesn't seem to be the solution to check for an unchecked check-box, any suggestions how to fix this?
Checkbox checked:
Checkbox unchecked:
Thanks in advance for your help
ninsky
If you let the 'required' of your CheckboxType to true, the constraints isTrue is not useful because the checkbox will always be true !
If change change that to :
$builder->add('conditions', CheckboxType::class, array('mapped' => false, 'required' => false, 'constraints' => new IsTrue(array("message" => "Bitte akzeptieren Sie noch die AGB und Nutzungsbedingungen."))));
With this configuration you can submit the form and if the box is not checked the constraints will send your message.
Hope this help ...
As a workaround, you can add a form listener to make sure you submit the value. Add following to the bottom of your buildForm() function:
$builder->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) {
$data = $event->getData();
if (!isset($data['conditions'])) {
$data['conditions'] = false;
}
$event->setData($data)
});
As another workaround, you can perform a check in controller and show flash message if request headers do not contain 'conditions'.
Symfony docs mention it:
$builder
->add('email', EmailType::class);
// ...
->add('termsAccepted', CheckboxType::class, array(
'mapped' => false,
'constraints' => new IsTrue(),
))
);
Well, I don't see why is not working for you so in the meantime I give you an alternative way :)
$builder->add('conditions', CheckboxType::class , array('mapped' => false, 'required' => true, 'attr'=>array('onchange'=>"try{setCustomValidity('')}catch(e){}",'oninvalid'=>"setCustomValidity('Bitte akzeptieren Sie noch die AGB und Nutzungsbedingungen.')")));
Hope this work for you.
I've run your code with everything but the CompanyFormType line and it is working as expected.
Could you remove this CompanyFormType line and give it a try ?
You have to set the validation group Overriding Default FOSUserBundle Forms
By default, the Registration validation group is used when validating
a new user registration. Unless you have overridden this value in the
configuration, make sure you add the validation group named
Registration to your name property.
How to do that you can find out here: Overriding Default FOSUserBundle Validation

Genemu JQueryColor Field Symfony2 error ColorPicker

I try to use Genemu JQueryColor Field with Symfony2
<?php
// ...
public function buildForm(FormBuilder $builder, array $options)
{
$builder
// ...
->add('color', 'genemu_jquerycolor')
->add('colorpicker', 'genemu_jquerycolor', array(
'widget' => 'image'
))
}
It runs Exception
Neither the property "colorpicker" nor one of the methods
"getColorpicker()", "colorpicker()", "isColorpicker()",
"hasColorpicker()", "__get()" exist and have public access in class
"KALAN\NetRDVBundle\Entity\Station
I try just
->add('colorpicker', 'genemu_jquerycolor', array(
'widget' => 'image'
))
No error, but just inpput text with code color
I try
->add('color', 'genemu_jquerycolor', array(
'widget' => 'image'))
No error, the background color is ok but i can change the color.
I try just
->add('colorpicker', 'genemu_jquerycolor', array(
'widget' => 'image'))
Or
->add('colorpicker', 'genemu_jquerycolor')
The error is the same
Neither the property "colorpicker" nor one of the methods
"getColorpicker()", "colorpicker()", "isColorpicker()",
"hasColorpicker()", "__get()" exist and have public access in class
"KALAN\NetRDVBundle\Entity\Station".
Even if i can't add
{{ form_widget(form.colorpicker) }}
May be its late maybe its not , the thing is like this.
Your class doesnt have the property colorpicker .
When you add a field to the builder , the builder will try to map it to the field of the entity you are making the formType for (in this case Station).
What you need to do is tell to the builder not to map that field. You can achieve this using the "mapped" property.
http://symfony.com/doc/current/reference/forms/types/form.html#mapped ------>Form type doc.

Symfony2 KnpMenuBundle - Following tutorial and came across this error

I followed this tutorial:
https://github.com/KnpLabs/KnpMenuBundle/blob/master/Resources/doc/index.md#installation
And have come across the following error:
An exception has been thrown during the rendering of a template ("Unable to generate a URL for the named route "page_show" as such route does not exist.") in /var/www/bundles/src/Acme/DemoBundle/Resources/views/Default/index.html.twig at line 4.
Is there a step I am missing here to pass something to a controller?
From link:
use Knp\Menu\FactoryInterface;
use Symfony\Component\DependencyInjection\ContainerAware;
class Builder extends ContainerAware
{
public function mainMenu(FactoryInterface $factory, array $options)
{
$menu = $factory->createItem('root');
$menu->addChild('Home', array('route' => 'homepage'));
$menu->addChild('About Me', array(
'route' => 'page_show',
'routeParameters' => array('id' => 42)
));
// ... add more children
return $menu;
}
}
To actually render the menu, just do the following from anywhere in any Twig template:
{{ knp_menu_render('AcmeDemoBundle:Builder:mainMenu') }}
Do a ./app/console router:debug - it will show you all the routes registered in your application. I am guessing page_show is not one of them.
The documentation you are using probably expects you to add your own routes/pages to the menu like this:
$menu->addChild('Home', array('route' => 'homepage'));
Where 'homepage' has to already exist. So does 'show_page'. So you need a controller somewhere that handles a request to the show_page route, or exchange show_page for a route that you have already defined in your app. Hope I made sense.
Following the tutorial exactly, this error is caused by line 25 in the file
2 // src/Acme/MainBundle/Menu/MenuBuilder.php
...
25 $menu->addChild('Home', array('route' => 'homepage'));
The tutorial code assumes that you have a route called 'homepage'. Assuming you set this up inside a custom Bundle, then a quick way to solve this problem so you can get the tutorial up and running is to go to...
// src/Acme/MainBundle/Resources/config/routing.yml
...and copy the homepage route from there (will look something like acme_main_bundle_homepage)

Unit tests failing when I use a custom view helper in the layout

So I have created my custom view helper and used it in layout.phtml like this:
<?php echo $this->applicationBar(); ?>
It is working flawlessly in the browser but my unit tests that were working before are failing now:
1) UnitTests\Application\Controller\IndexControllerTest::testIndexActionCanBeAccessed
Zend\ServiceManager\Exception\ServiceNotFoundException: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for applicationBar
When I comment out the view helper in the layout file, test passes again.
I have the same problem, and i solved it in not a good way (but it solved for my specific problem).
The phpunit tests is not finding my factories view helpers, but it is finding my invokables. Then, i did the following:
public function getViewHelperConfig() {
return array(
'factories' => array(
'aplicationBar' => function($service) {
$applicationBar = new ApplicationBar();
return $applicationBar;
},
),
'invokables' => array(
'applicationBar' => 'Application\View\Helper\ApplicationBar',
),
);
When i use the browser, it uses the correct Factory. When i use phpunit, it uses the invokables.
The problem happens when i need to set some parameters. And then, i set some default parameters, that will be used only by phpunit.
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper;
class ApplicationBar extends AbstractHelper {
protected $parameter;
public function __construct($parameter = 'something') {
$this->parameter = $parameter;
}
public function __invoke() {
return $this->parameter;
}
}
It is not the best solution, but if i solve it in a better way, i will post here.

Add CSS attributes to Symfony form labels?

I try to add some css attributes to labels in my custom sfForm but I can't achieve it.
In my custom class myForm extends sfForm, I create all textfields dynamically:
public function configure()
{
$widgetFixtures = array();
foreach ($fixtures as $fixture) {
$widgetFixtures[$fixture->getId()] = new sfWidgetFormInputText(
array('label' => $fixture->getTeamNameDom()),
// I would like to add something like: array('class' => $fixture->getCSS()),
array('value' => $fixture->getScore1(), 'readonly' => 'readonly')
);
}
$this->setWidgets($widgetFixtures);
}
I tried to format the rendering with setFormFormatterName but without success.
Note: I can't use renderLabel($value, $attributes = array()) in the template because I get the CSS class from the DB (as you may have seen, I have to use: $fixture->getCSS()).
Could someone shed my light?
Many thanks.
Here is how I solved it.
I took both suggestions from johnwards and richsage and put them together :
"This sort of stuff should be handled in the view/action."
"Access to the options/attributes passed to the Widget itself."
First, I add the CSS class to the input itself (even if I will not use it).
In my custom class myForm extends sfForm,
foreach ($fixtures as $fixture) {
$widgetFixtures[$fixture->getId()] = new sfWidgetFormInputText(
array('label' => $fixture->getTeamNameDom()),
array('value' => $fixture->getScore1(),
'readonly' => 'readonly',
'class' => $fixture->getCSS())
);
}
Then, in the template, instead of using echo $form;, I add the CSS class to the label as shown below:
foreach ($form as $widgetId => $widget) {
...
$labelClass = $widget->getWidget()->getAttribute('class');
echo '<td>'.$widget->renderLabel(null, array('class' => $labelClass)).'</td>';
...
}
Maybe it is not the best way to solve this issue but it works.
Thanks all for your feedback!
What you're trying to do seems possible but your greyed out syntax seems a little off. Try this:
$widgetFixtures[$fixture->getId()] = new sfWidgetFormInputText(
array('label' => $fixture->getTeamNameDom()),
array('class' => $fixture->getCSS()),
array('value' => $fixture->getScore1(), 'readonly' => 'readonly')
);
... or check "The sfWidgetForm Base Class" section here: http://www.symfony-project.org/forms/1_4/en/A-Widgets
The class attribute needs to be passed in as an array in the second parameter for all form widgets.
$this->setWidget('foo', new sfWidgetFormInputText(array(),array('class','fooclass'));
You could try overriding the widget class if you want to add CSS to labels - specifically the methods that render the label. You could then do something like
$foo = new myWidgetFormInputText(array("myCSSClass" => $fixture->getCSS()));
and then override your renderLabel() method or similar in your widget. Your widget will have access to the options you pass in - in the above example myCSSClass is the option key. You can then apply this class value to your widget's label.
It's much easier than that. Just apply CSS to the label for tag...
label[for=payment_cardNumber]
{
margin-top: 20px;
color: red;
}

Resources