Multiple forms on same page - php

I use FOSUserBundle with Symfony2. By default FOSUserBundle profile edit and password change is on different pages, but I need these forms on one page and add one custom form. My idea is to override profile controller with additional forms, but maybe there is more easier way? I also had idea to post all forms in different controllers, but problem is that I need to show errors for any field and I don't think, that is good practice to save object in flash.

I got a sidebar with the login and a few teaser on my page in my layout, so it's available from everywhere.
Just do the following in the twig.html file you want to use to display the login/registration etc
{% extends "::base.html.twig" %}
{% block title %} Title {% endblock %}
{% block sidebar %}
{% render controller("FOSUserBundle:Security:Login") %}
{# Other Controller you want to render here #}
{% endblock %}
My login.twig.html file looks like this
{# app\Resources\FOSUserBunle\Security\views\login.twig.html #}
{% block fos_user_content %}
<div class="teaser-header">Login</div>
<form role="form" action="{{ path("fos_user_security_check") }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token }}" />
<div class="form-group">
<label for="username">{{ 'MyLog Username'|trans }}</label>
<input class="form-control" type="text" id="username" name="_username" placeholder="Your Username" required="required" />
</div>
<div class="form-group">
<label for="password">{{ 'Password'|trans }}</label>
<input class="form-control" type="password" id="password" name="_password" placeholder="Your Password" required="required" />
</div>
<input type="submit" id="_submit" name="_submit" value="{{ 'Segel setzen'|trans }}" />
</form>
{% endblock %}

Related

Symfony form_login does not work, but http_basic does

I'm trying to implement a login function in my Symfony2 application, using the built-in login functionnality from Symfony.
I can access the /login page fine, but when I type my username and password, and hit login, it just brings me back to the /login page, without any error message.
If I try to connect with the wrong username and/or password, or none, the same thing happens: I get redirected to /login with no error message.
I tried to connect using http_basic, and it worked. So I suppose my users provider is good, but I don't get what prevents the login from working.
login.html.twig
{% extends "::layout.html.twig" %}
{% block title %}Login{% endblock %}
{% block stylesheets %}
{{ parent() }}
{% stylesheets 'bundles/seinput/css/login/*' filter='cssrewrite' %}
<link rel="stylesheet" type="text/css" charset="UTF-8" media="all" href="{{ asset_url }}"/>
{% endstylesheets %}
{% endblock %}
{% block body %}
<form action="{{ path('login') }}" method="post">
<div class="field">
<label for="username">Username:</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" />
</div>
<div class="field">
<label for="password">Password:</label>
<input type="password" id="password" name="_password" />
</div>
<div class="form-button">
<button class="btn btn-success" type="submit">login</button>
</div>
{% if error %}
<div>{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% else %}
<div>No error</div>
{% endif %}
<input type="hidden" name="_target_path" value="/" />
</form>
{% endblock %}
edit: Now that the answer is provided, and since the error comes from a single line in the twig file, I removed the other files, to make the question more readable to future readers.
I see that your form have and action that points to login URL, ¿you can try to modify this to login_check?
I think that your problem is near here
<form action="{{ path('login_check') }}" method="post">

Theme paradigm in Symfony2 [duplicate]

I've installed Symfony2, FOS User Bundle and Twitter Bootstrap.
Then I setup the /app/Resources/FOSUserBundle/views/layout.html.twig template to override FOSUserBundle to use my site template.
It all works if I have a link to /login on the homepage.
Now I want to implement a template like the hero template where the login form is part of the main template.
The closest I've got is to use this in the main template:
{% render controller("FOSUserBundle:Security:login") %}
I can override the layout html to not extend main template, but this removes all styling from /login
Any ideas how I can handle both scenarios?
You were almost there :)
you can include the login form in any other template using the render function.
{% render controller("FOSUserBundle:Security:login") %}
... you just have to create app/Resources/FOSUserBundle/views/Security/login.html.twig and ommit the wrapping {% block fos_user_content %} found in FOSUserBundle's login.html.twig in order to have it return the form directly:
{% if error %}
<div>{{ error|trans }}</div>
{% endif %}
<form action="{{ path("fos_user_security_check") }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token }}" />
<label for="username">{{ 'security.login.username'|trans }}</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" required="required" />
<label for="password">{{ 'security.login.password'|trans }}</label>
<input type="password" id="password" name="_password" required="required" />
<input type="checkbox" id="remember_me" name="_remember_me" value="on" />
<label for="remember_me">{{ 'security.login.remember_me'|trans }}</label>
<input type="submit" id="_submit" name="_submit" value="{{ 'security.login.submit'|trans }}" />
</form>
Then adjust it to fit your template.
Richard Miller's post has helped me achieve what I was trying to do.
http://richardmiller.co.uk/2013/02/18/symfony2-ajax-and-full-page-templates/
{% extends app.request.attributes.get('partial')
? '::ajax-layout.html.twig'
: '::full-layout.html.twig' %}
I couldn't get app.request.partial to work, and decided choosing based on xmlRequest wasn't ideal.

Overriding "Change Password" Template from FOS User Bundle

I did some research and sadly couldn't find any help for that.
So I'm rendering the FOSUserBundle ChangePasswordAction into a template of mine, but it displays the default template given from the vendor.
My template where the controller is rendered:
{% block body %}
<h2>Einstellungen</h2>
<br/>
<h4>Ändern Sie ihr Passwort</h4>
{% render controller("FOSUserBundle:ChangePassword:changePassword") %}
{% endblock %}
My template for the ChangePasswordAction, the path is app/Resources/FOSUserBundle/views/ChangePassword/changePassword.html.twig:
{% block fos_user_content %}
{% trans_default_domain 'FOSUserBundle' %}
<form action="{{ path('fos_user_change_password') }}" {{ form_enctype(form) }} method="POST" class="fos_user_change_password">
{{ form_start(form) }}
{{ form_errors(form) }}
<p><span class="edit_left_date">{{ form_label(form.current_password, 'Jetziges Passwort') }} </span>
<span class="edit_right">{{ form_widget(form.current_password) }}</span></p>
<p><span class="edit_left_date">{{ form_label(form.new_password, 'Neues Passwort') }} </span>
<span class="edit_right">{{ form_widget(form.new_password) }}</span></p>
<p><span class="edit_left_date">{{ form_label(form.new_password_confirmation 'Bestätigen Sie ihr neues Passwort') }} </span>
<span class="edit_right">{{ form_widget(form.new_password_confirmation) }}</span></p>
<div>
<input type="submit" value="{{ 'Speichern'|trans }}" />
</div>
{{ form_end(form) }}
</form>
{% endblock %}
What drives me crazy is that i render the login controller from the FOSUserBundle the same way in my layout.html.twig and it's working perfectly there.
The snippet of code from the layout:
{% block sidebar %}
{% render controller("FOSUserBundle:Security:Login") %}
{% endblock %}
and the app/Resources/FOSUserBundle/views/Security/login.html.twig:
{% block fos_user_content %}
<div class="teaser-header">Login</div>
<form role="form" action="{{ path("fos_user_security_check") }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token }}" />
<div class="form-group">
<label for="username">{{ 'MyLog Username'|trans }}</label>
<input class="form-control" type="text" id="username" name="_username" placeholder="Your Username" required="required" />
</div>
<div class="form-group">
<label for="password">{{ 'Password'|trans }}</label>
<input class="form-control" type="password" id="password" name="_password" placeholder="Your Password" required="required" />
</div>
<input type="submit" id="_submit" name="_submit" value="{{ 'Segel setzen'|trans }}" />
<a id="passwordForget" href={{ path('fos_user_resetting_request') }}>Password vergessen?</a>
</form>
{% endblock %}
Am i missing something or what am i doing wrong so i can't override the changePassword Template?
Moving from comments to an answer:
Have you cleared your cache since adding the new template?
What you basically do is you create a user bundle of your own + set it's parent to the FOS user bundle. (You should already have done this step)
Then you set the template in:
MyCompany/MyProject/UserBundle/Resources/views/Resetting/request.html.twig
Because of the fact that the file in the FOS user bundle is on the same place, your file will overwrite that template.
If you think you've done everything correctly and still it doesn't work, you can try to clear the cache with a Symfony command in the terminal, or in some cases manually delete the cache directories - 'app/cache/dev' or 'app/cache/prod'.

FOSUerBundle override template not working

I'm trying to override the login and register templates for FOSUserBundle but I can't get it working, I'm doing what documentation says, but nothing happens all I can see is the default templates :S
This is my app\Resources\FOSUserBundle\views\Security\login.html.twig
{% extends "FOSUserBundle::layout.html.twig" %}
{% block fos_user_content %}
{% if error %}
<div>{{ error|trans({}, 'FOSUserBundle') }}</div>
{% endif %}
<p>Login!</p>
<form action="{{ path("fos_user_security_check") }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token }}" />
<label for="username">{{ 'security.login.username'|trans({}, 'FOSUserBundle') }}</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" required="required" />
<label for="password">{{ 'security.login.password'|trans({}, 'FOSUserBundle') }}</label>
<input type="password" id="password" name="_password" required="required" />
<input type="checkbox" id="remember_me" name="_remember_me" value="on" />
<label for="remember_me">{{ 'security.login.remember_me'|trans({}, 'FOSUserBundle') }}</label>
<input type="submit" id="_submit" name="_submit" value="{{ 'security.login.submit'|trans({}, 'FOSUserBundle') }}" />
</form>
{% endblock fos_user_content %}
And this is my app\Resources\FOSUserBundle\views\layout.html.twig
{% extends '::base.html.twig' %}
{% block body %}
<div class="container">
{% for type, messages in app.session.flashbag.all() %}
{% for key, message in messages %}
<div class="flash-{{ type }}">
{{ message|trans({}, 'FOSUserBundle') }}
</div>
{% endfor %}
{% endfor %}
{% block fos_user_content %}{% endblock %}
</div>
{% endblock %}
Make sure you are extending fosUserBundle in your userbundle file:
<?php
namespace Radsphere\UserBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class RadsphereUserBundle extends Bundle
{
public function getParent()
{
return 'FOSUserBundle';
}
}
In addition, make sure the twig template, which you are extending, exists in the same folder structure like in FosUserBundle:
For example I extended login.html.twig and its location is at
src/Radsphere/UserBundle/Resources/views/security/login.html.twig
Just to bring some attention to an alternative for people that may end up here, as per Sam Dufel's comment, this was caused (for me) by the cache folder not fully clearing (itself an issue caused by vagrant sharing folders and permissions)
Manually deleting the app/cache folder fixes it.

Symfony 2.3 how do you group the buttons together in one form group?

Right now i have a FormType that contains the following:
$builder->add('name','text')
->add('save','submit',array('label'=>'Save', 'attr'=>array('class'=>'btn btn-primary')))
->add('reset','reset',array('label'=>'Reset Form', 'attr'=>array('class'=>'btn btn-warning')));
Right now i have a little bit of form themeing going on that renders the above as:
<form method="post" action="">
<input type="hidden" name="_csrf_token" value="*********" />
<div class="form-group">
<label class="col-4">Name</label>
<input type="text" name="form[name]" value="" placeholder="Name" />
</div>
<div class="form-group">
<input type="submit" name="form[save]" value="Save" class="btn btn-primary" />
</div>
<div class="form-group">
<input type="reset" name="form[reset]" value="Reset" class="btn btn-warning" />
</div>
</form>
However what I would like the output to be is:
<form method="post" action="">
<input type="hidden" name="_csrf_token" value="*********" />
<div class="form-group">
<label class="col-4">Name</label>
<input type="text" name="form[name]" value="" placeholder="Name" />
</div>
<div class="form-group">
<input type="submit" name="form[save]" value="Save" class="btn btn-primary" />
<input type="reset" name="form[reset]" value="Reset" class="btn btn-warning" />
</div>
</form>
Notice the buttons are in the same form group wrapper div. I want to know if there is a way to do this using only the FormType or editing the Form Theme. I dont want to change the views from using:
{{ form(form,{'method':'POST','attr':{'class':'form-horizontal'} }) }}
I am aware this can be accomplished if I render the buttons from the form in a custom manner.
Update
A bundle that solves this for you that basically does what i suggest but nicer:
http://bootstrap.braincrafted.com/components.html#forms
This is far from the most elegant way to do this but i havent found any other means to do this.
I have a working solution that involves modifying the FormType a bit and also overriding some blocks in form_div_layout.html.twig
{# form_div_layout.html.twig #}
{% block button_row %}
{% spaceless %}
{% if 'data-first-button' in attr %}
<div class="form-group">
<div class="col-12">
{% endif %}
{{ form_widget(form) }}
{% if 'data-last-button' in attr %}
</div>
</div>
{% endif %}
{% endspaceless %}
{% endblock button_row %}
{% block button_attributes %}
{% spaceless %}
id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif %}
{% for attrname, attrvalue in attr %}{% if attrvalue != 'data-first-button' and attrvalue != 'data-last-button'%}{{ attrname }}="{{ attrvalue }}"{%endif%}{% endfor %}
{% endspaceless %}
{% endblock button_attributes %}
What this does is it looks for the data-first-button and data-last-button attributes on buttons and adds the containing divs for the respective ones. Then in the button attributes block we look for those attributes and ignore them. Then in the form type we just have to add the attr to the right buttons like this:
$builder->add('name','text')
->add('save','submit',array('label'=>'Save', 'attr'=>array('class'=>'btn btn-primary','data-first-button')))
->add('reset','reset',array('label'=>'Reset Form', 'attr'=>array('class'=>'btn btn-warning','data-last-button')));
I have a better answer (a more modern solution than the last accepted answer from 2 yrs ago.
Comment out in your controller where your adding those elements
/* -
->add('cancel', 'button', array())
->add('save', 'submit', array())
*/
Now set up your form like this
{{ form_start(form, {'attr': {'id': 'your-form-id'},}) }}
{{ form_errors(form) }}
{{ form_row(form.name) }}
<div class="form-group">
<button id="form_reset"name="form[reset]" type="button">Reset</button>
<button id="form_save" name="form[save]" type="submit">Save Form</button>
</div>
{{ form_end(form) }}
You always have the option of a jQuery solution, but the above is the correct way to customize your form
or a jQuery solution might look something like this;
var formInputSave = $('input:form[save]'),
formInputReset = $('input:form[reset]'),
formGroupReset = formInputReset.parent();
//save the form group with the form[save] in it.
//Append the reset input to it, then remove the initial form group
$(formInputSave).append(formInputReset);
$(formGroupReset).empty();

Categories