I have a problem with a helper in Symfony2. I have a helper which works fine. And I have a view made with PHP and HTMl without sintax errors.
I need to make a foreach and in that foreach, I need to create a button which call my helper which some information of this iteration and If an user click in this button, call this helper with this information.
Some like:
foreach $i...
<form action="<?php echo $view['entities']->HelperFunction($i) ?>" >
<button type="submit">Helper Call</button>
...
end foreach
My problem is that in each iteration, automatically the helper is called and his function executed. I need to execute only the helper when I click in the button generated.
Any idea?
Thanks in advance.
You should use symfony forms for this or if it is something custom and you don't have any field inside the form you just for some reason wants to use a function, you can still use symfony not pure PHP in your controller which render the view pass the variable $view['entities'] to the twig like this :
public function newAction(Request $request)
{
/* your codes */
return $this->render('yourBundle:Default:yourtwigfile.html.twig', array(
'view' => $view['entities'],
));
PS : yourBundle:Default:yourtwigfile.html.twig : Default is the folder by default which is yourBundle/Resources/views, if you have a folder inside views like yourBundle/Resources/views/folder it would be yourBundle:folder:yourtwigfile.html.twig
Then inside the twig file in your action use this :
{% for i in 0..10 %}
<form action="{% view.HelperFunction(i) %}" >
<button type="submit">Helper Call</button>
...
{%endfor%}
i didn't test this but it should work, i don't know why you want to do this but it will generate lot of forms depending on how many time you want the for to run.
Related
I want to pass a object from the blade file to the controller file. The purpose is when the user click an edit button the user will get a form which is filled with the previous input data. I am using this code in the blade file:
Edit
But When I want to get the passed object from the controller's edit method I get a null. My Controller code is like this now:
public function edit(FeesType $feesType)
{
//
dump($feesType->name);
return view('feestype.edit',['feesType'=>$feesType]);
}
Here I have dump the $feesType object but I get a null. Please help me how can I solve this problem.
Thanks in advance
Route model binding works a bit different here is the documentation
What you need to do is have your route like this:
Route::get('feestype/{feesType}/edit', 'YourController#edit')->name('feestype.edit');
then in your view
Edit
-- EDIT
using a resource file:
Route::resource('feestype', 'YourController')
the link will be built the same as above:
{{ route('feestype.edit', $feesType) }}
you should change your Route to :
Route::put('feestype/{id}/edit', 'YourController#edit');
For update and edit you should use put not get.
Note that for this code:
Edit
first you should compact $feestype in YourController then use your code in blade.
Now the code in the blade file is
Edit
The controller file contains this code:
public function edit(FeesType $feesType)
{
//
$feesType = FeesType::find($feesType->id);
dump($feesType->name);
return view('feestype.edit',['feesType'=>$feesType]);
}
And here is my Route definition:
Route::resource('feestype','FeesTypesController');
And the browser shows this message:
In the form I have to define a handler like admin/login. Then it changes the page when I send it. I also tried using public function indexAction() handler and only using the controller admin without a handler, but then nothing happens.
Any help would be greatly appreciated.
Edit:
I wanted to have a error message but it was not so big a site that i wanted to make a form class.
The way i eventually fixed it was the following:
First i use $this->view->pick('admin/index'); in the handler to select my old view.
Next i send a variable like a error message with $this->view->setVars(['username' => $user->name,]); in the handler.
Last i used it with volt in the previous view views/admin/index.phtml like this {{ username }}
If you are using a form object you can then use the following code in your volt template
{{ form('myform', 'method':'post', 'role': 'form') }}
This will post your data to the same controller/action that invoked the form. From then you will be able to handle the posted data using valid() in the form as well as request->isPost()
I render my header.twig from the base.twig file via the render function. So in my base.twig there is the following code to trigger header controller:
{{ render(controller('MyBundle:Global:header')) }}
That controller renders the header.twig. In this twig file there the the following code link for changing the language:
<img src="{{ asset('flags/'~app.request.locale~'.png', 'img') }}" />
The objects form app.request.get('_route') and app.request.get('_route_params') both return null.
app.request.get('_route')
If I run the same code link directly in the base.twig the request returns the correct objects. Looks like because the header.twig has it own controller the request are not working. Is it possible to request the route and parametsr of the active url in a other way?
Adding to #Gustek's answer because I missed the actual issue in the first case.
You are actually rendering a sub request so the _route and _route_params are from the sub request rather than the main request. As you are using a controller the cleanest approach would be to get the parameters from the master request and pass those in as parameters in the controller call. You could pass them in through the render call (as #Gustek has answered) but that would mean you would mean to do it with every call, or you could pass the request stack into the twig session but that would be unnecessary extra work.
public function headerAction(Request $request)
{
$masterRequest = $this->container->get('request_stack')->getMasterRequest();
//...
return $this->render('MyBundle:Global:header.html.twig', [
//...
'_route' => $masterRequest->attributes->get('_route'),
'_route_params' => $masterRequest->attributes->get('_route_params'),
]);
}
controller method takes 2 optional arguments.
http://symfony.com/doc/current/reference/twig_reference.html#controller
Not 100% sure about it but maybe this will work:
{{ render(controller('MyBundle:Global:header',
{
'_route': app.request.get('_route'),
'_route_params': app.request.get('_route_params')
}
)) }}
I've created a new form type for a simple one field newsletter signup form. What's the best way to embed this across different pages, multiple times on my site?
I could create a new instance of this form with a different name in every controller to show in my twig templates, but this seems a little messy. Ideally I'd like to be able to add more than one form on a page, and add them easily to a template.
I've tried {% render controller('MyBundle:EmailSubscribe:subscribe') %} but this doesn't work with multiple inserts, and I'm sure there's a better way anyway. Any ideas?
May be with Twig extension? This kind of task is the next one in my current project (e-commerce project where I need to display multiple addToCart forms on category pages), I'm also planning to do this with Twig function, for example (I did'nt test it yet):
private $formFactory;
public function __construct(FormFactoryInterface $formFactory)
{
$this->formFactory = $formFactory;
}
public function getFunctions() {
return [
new \Twig_SimpleFunction('newsletter_form', [$this, 'getNewsletterForm']),
];
}
public function getNewsletterForm()
{
$formFactory = $this->formFactory;
$form = $formFactory->create('my_form_alias', null_OR_data);
return $form->createView();
}
and use it in template as newsletter_form
Im a fan of xurshid29's Answer
What I do is simplay render the controller like your answer suggests. But that causes only one form to get processed, and leaves the unprocessed forms with errors like Cannot extra fields and so forth.
The Solution:
Pass the request from the original controller.
In Controller
function myAction(Request $request){
$this->render('path:to:template.html.twig', array('request'=>$request));
}
And In my Twig Template I simply pass the request to that controller.
{% render(controller('path:to:controller',{request:request} %}
And now you can create a base template for that form and include it in any template all across the site. This was especially useful for me with FOSUserBundle!
There may be some kind of twig function app.request ? I've been too lazy to try look it up. But in that case you don't have to pass request from original controller.
Extra tips on this subject
What I like to do that allows me to insert my forms anywhere for rapid dev is to build a controller/template for each form, like a "Join our Mailing List" or something.
Controller - The goal of this controller is to process the form and output "success" or show the form.
public function emailSubscribeFormAction(Request $request){
$email = new Email() //Presumed Entity for form
$form = /* Create Form Here */->getForm();
$form->handleRequest($request);
if($form->isValid()){
$form = "success"; //Change form into a string
}
$this->render('path:to:email-form.html.twig', array(
'form'=>($form=="success") ? $form : $form->createView();, // Either pass success or the form view
'request'=>$request
}
Twig email-form.html.twig
{% if form == "success" %}
<h4 id="form-success">Thanks for joining!</h4>
<script>
window.location = "#form-success" /*Bring the user back to the success message*/
</script>
{% else %}
<h4>Come on, Join Our Mailing List!</h4>
{{ form(form) }}
{% endif %}
Now you can render that controller anywhere and not have to worry about another thing about it.
Can work with multiple forms but I may have read there are drawbacks to rendering controllers like this?
If I understood your problem correctly you want to embed the same form multiple times in a page and this is to be done for multiple pages. So lets say that for page_1 you want to embed the subscribe_form N times you can obviously create a form and add this form type N times like this:
$form = $this->createFormBuilder()
->add('subscribe1',new SubscribeType())
->add('subscribe2',new SubscribeType())
...
->add('subscribeN',new SubscribeType())
->getForm();
So you can also do this in a for loop like this:
$form = $this->createFormBuilder();
for ($i = 1; $i<N+1; $i++){
$formName = 'subscribe'.$i;
$form->add($formName,new SubscribeType());
}
$form->getForm();
Now you can include this code in a controller as you said and pass the variable N as argument in each of your twig templates. Moreover, you can do this through javascript especially if you want to add these forms(SubscribeType) dynamically using allow_add option in your form. Documentation about this is here: http://symfony.com/doc/current/cookbook/form/form_collections.html#allowing-new-tags-with-the-prototype.
Hope that helps otherwise inform me if I misunderstood your problem.
My site I have some content can be voted (+/-). It is working fine now, when all content has its own voter.
Now I'm looking for a way to create a single voting bundle with a entity(votedModel,votedId, user, vote).
Basically the bundle is ready. My problem is how to use it. I'd like to be able to do something like:
class ... extends Controller {
function showAction(Request $request,$id) {
...
$voter=new Voter('myCOntentType',$id,$userid);
...
return $this->render('...', array('voter'=>$voter->getVoter(),...))
}
}
getVoter() would create the voter view.
but I'm stacked how exactly start. I tried to call for the other controller in this manner, but can't create the voter form.
It worked with $voter=$this->forward('VoterbundleNewAction', array('id=>$id,'user'=>$user)->getContent();But this wasn't I had in mind.
I think my approach is all wrong and I may need to do this as service. I cant find my way around.
You can use include or render in your twig template to get other templates' output. So you could create a template (say, voter.html.twig) that contains the HTML for your voting system, and in the Twig, in any place where you need a voter, you could use:
{% include "AcmeVoterBundle:Voter:voter.html.twig" %}
or
{% render "AcmeVoterBundle:Voter:voter" with {"item": item} %}
In the first example, you simply include another template (see also: http://symfony.com/doc/current/book/templating.html#including-other-templates), in the latter situation you actually execute another action method of a controller and the output of that is put into your current template (see also: http://symfony.com/doc/current/book/templating.html#embedding-controllers)