Symfony2 - Display data on same page - symfony

I am having a little trouble displaying data on the same page again. I have a simple view
{% block main %}
<div class="col-md-4">
<section class="panel panel-default">
<div class="panel-body">
<form action="{{ path('NickAlertBundle_tsubmit') }}" method="post" enctype="multipart/form-data" class="terminalForm" id="terminalForm">
<div class="row">
<div class="col-md-12">
<input type="text" class="addMargin" id="terminal_command" name="terminal_command" placeholder=">">
</div>
</div>
<div class="row">
<div class="col-md-8 col-md-offset-4">
<input type="submit" class="btn btn-default" id="terminal_submit" value="Submit">
</div>
</div>
</form>
</div>
</section>
</div>
<div class="col-md-8" id="terminal-window">
</div>
{% endblock %}
So on that view I display a form. The user enters some data and then I want the response display in the terminal-window div. So I have set up routes
NickAlertBundle_terminal:
pattern: /terminal
defaults: { _controller: NickAlertBundle:Alert:terminal }
methods: [GET]
NickAlertBundle_tsubmit:
pattern: /terminal
defaults: { _controller: NickAlertBundle:Alert:tcreate }
methods: [POST]
The GET simply renders the initial page, the POST controller is doing
public function terminalAction()
{
return $this->render('NickAlertBundle:Page:terminal.html.twig');
}
public function tcreateAction(Request $request)
{
try {
$terminal_command = strtoupper($request->get('terminal_command'));
$uapiService = $this->container->get('alert_bundle.api_service');
$commandData = $uapiService->terminalService($terminal_command);
return $this->render('NickAlertBundle:Page:terminal.html.twig', array(
'data' => $commandData,
));
}catch (Exception $e) {
}
}
Is this the correct way to do it? Reason I ask is because if I add the following to my div in the view
{% for d in data %}
{{ d }}
{% endfor %}
I obviously get the following error
Variable "data" does not exist in...
So how can I render the data that is returned from the form submission?
Thanks

This is because Twig expects data to be passed to the template the first time the page is rendered (which is handled by the initial GET controller). To remedy the issue, you need to check to determine if data has been defined.
I would do something like this:
{% if data is defined %}
{% for d in data %}
{{ d }}
{% endfor %}
{% endif %}
Now, when the form initially loads but is empty, Twig first checks to see if the variables was passed to it, and since it doesn't, it just skips the for loop altogether.
The other option would be to simply pass an empty array in your first controller. I would view it as less desirable unless you are persisting data and at that point it would be practical anyway.

Related

Omines Datatables with Turbo and Stimulus

I am trying to use Turbo in a new Symfony development. I'm following Turbo: Drive, Frames & Streams as a reference! and previously Symfony UX: Stimulus. Both topics are new to me and as if that weren't enough, I don't have much experience with Javascript.
All good except that I have not been able to get Omines Datatables to work under this scheme. I understand that I must create a Stimulus component but I have not achieved even the most basic thing, which is to load the Datatable.
I wonder if someone can guide me or if they have gone through the same thing, maybe they can provide a practical example of how to do it. Is it too much to ask?
In general, I usually load the Datatables in the following way:
{% block body %}
...
<div class="row">
<div class="col-12">
<div id="app_provinciaList">
<div class="d-flex justify-content-center">
<div class="spinner-border m-5" role="status">
<span class="sr-only">Cargando...</span>
</div>
</div>
</div>
</div>
</div>
...
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script>
$(function () {
var grillaApp_provincias = $('#app_provinciaList').initDataTables( {{ datatable_settings(datatable) }}, {
searching: true,
}).then(function (dt) {
dt.on('init', function(settings, json) {
$('#dt_filter input').attr("placeholder", "Provincia...");
$('#dt_filter input').width(300);
});
});
});
</script>
{% endblock %}

Flask-WTForms .validate_on_submit() never executes

So basically I want to have a Updateform() form that allows users to update their account details. All my other forms (register, etc.) work perfectly fine but this specific form never validates on submit. Hence when I press the submit button the page just refreshes but the .validate_on_submit() code doesn't execute.
I've looked through the forums and a common issue I found is the .CSRF token missing, but I'm using form.hidden_tag() which I read should work perfectly fine. So it seems that my issue is unique.
I've been looking on the forums for hours but haven't found a solution.
Here is my form code:
class Updateform(FlaskForm):
email = StringField('Email:', validators=[DataRequired(), Email()])
picture = FileField('Update Profile Picture:', validators=[FileAllowed(['jpg', 'png'])])
submit = SubmitField("Update")
def validate_email(self, email):
if email.data != User.email:
if User.query.filter_by(email=email.data).first():
raise ValidationError('Email has already been registered')
Here is the route:
#users.route('/account', methods=['GET', 'POST'])
#login_required
def account():
form = Updateform()
print("hello")
if form.validate_on_submit():
print(form)
print("YES!!!")
name = current_user.name
pic = add_profile_pic(form.picture.data, name)
current_user.profile_image = pic
current_user.email = form.email.data
db.session.commit()
flash("Account Updated")
# elif request.method == "GET":
# form.email = current_user.email
profile_image = url_for('static', filename='profile_pics/'+current_user.profile_image)
return render_template('account.html', profile_image=profile_image, form=form)
And here is the html code:
{% extends "base.html" %}
{% block content %}
<div align="center">
Hi {{ current_user.name }}<br>
<img align="center" src="{{ url_for('static', filename='profile_pics/'+current_user.profile_image) }}">
</div>
<div class="container">
<form method="post">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.email.label(class='form-group') }}
{{ form.email(class='form-control') }}
</div>
<div class="form-group">
{{ form.picture.label(class='form-group') }}
{{ form.picture(class='form-control') }}
</div>
<div class="form-group">
{{ form.submit() }}
</div>
</form>
</div>
{% endblock %}
The extra classes you see are from the bootstrap library incase anyone is wondering.
Hello you could find out what the problem is by adding a else for you if form.validate_on_submit(): and have it do this
for error in form.email.errors:
print(error)
for error in form.picture.errors:
print(error)
this should tell you what is not working hope this helps and I have not tested this so it could have typos

Fetching objects from database in Symfony 2.7.3

I'm trying to show some object properties stored on the database. I've got the controller, the Entity, and the view. I'get no excepctions but I can't see the object properties.
Controller:
/**
* #Route ("/ov", name="ov")
*/
public function select(){
$a=$this->getDoctrine()->getRepository('AppBundle:PC')->find(2);
if(!$a){
throw $this->createNotFoundExcepction('No PC');
}
return $this->render('PcDetailed.html.twig', array('pcs' => $a));
}
View:
{% extends 'master.html.twig' %}
{% block divCentral %}
<div class="row">
<p>Nom del pc</p>
<div class="small-6 small-centered columns">
{% for pc in pcs %}
<p>{{ pc.nom }}</p>
{% endfor %}
</div>
</div>
{% endblock %}
Edit:
Finally, like Chris says, the problem is 'cause on the View I'm using I'm trying to iterate is an object, not an array. That's why doesn't work.
That's the way I must do it:
return $this->render('PcDetailed.html.twig', array('pcs' => array($a)));
In your controller you get the PC with id 2 and pass it to the view.
In the view you are now trying to iterate over this object. I have no idea what TWIG does when you try to iterate over something that is not an array or a collection but maybe it just fails silently.
To fix it, change your controller code to send an array to the view:
return $this->render('PcDetailed.html.twig', array('pcs' => array($a)));

Different views according to url in symfony2?

Suppose in my twig file I have following codes. Everything is working fine how to have different view if I click page number in Pagination tab.
When I click page no2 it should have different output. Eg
<p> This is page no2</p>
My url
http://localhost/project/web/app_dev.php/funfact/2
When I check current url using
{% if app.request.attributes.get('_route') == 'funfact/2' %}
</p> this is page no 2</p>
{%endif%}
it is not giving the above output.
How do I match current url with http://localhost/project/web/app_dev.php/funfact/2
Also in Phpstorm its giving me Alias 'Sensio\Bundle\FrameworkExtraBundle\Configuration\Route' is never used
In my twig view.html.twig
This is page 1
<div class="row">
<ul class="pagination pagination-lg">
<li>«</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>»</li>
</ul>
</div>
routing.yml:
funfact:
path: /funfact/{page}
defaults: { _controller: HomeBundle:FunFact:funView, page: 1 }
Controller Class
class FunFactController extends Controller
{
/**
* #Route("/funfact/{page}"),defaults={"page" = 1})
*/
public function funViewAction($page)
{
return $this->render('HomeBundle::funfact.html.twig');
}
}
Try this code
{% if 'funfact/2' in app.request.uri %}
</p>this is page no 2</p>
{% endif %}

Adding a CSS class to fields in django.contrib.auth.views.login

I'm still fairly new to django, and have come across Django forms for the first time through my use of the django.contrib.auth.views.login view, used when Django needs a user to authenticate.
I cannot however figure out how to add a CSS class to the username and password fields and the documentation doesn't specify how I can achieve it. Ideally I'd like to simply add the additional info to the template tag, such as {{ form.username | class="usernameclass" }} or whatever, or even write the field out manually, such as <input type="{{ form.password.type }}" name="{{ form.password.name }}" class="form-field-password"/>, but if I need to add a custom view to achieve this I can try that way.
The files related to this are below:
templates/login.html:
{% load url from future %}
...
<form method="post" action="{% url 'django.contrib.auth.views.login' %}">
{% csrf_token %}
<span class="heading">{{ form.username.label_tag }}</span><br/>
{{ form.username }}<br/>
<span class="heading">{{ form.password.label_tag }}</span><br/>
{{ form.password }}<br/>
<div id="login-button">
<input type="submit" value="Log In" />
<input type="hidden" name="next" value="{{ next }}" />
</div>
</form>
...
settings.py:
...
LOGIN_URL = '/login/'
...
urls.py
...
urlpatterns = patterns('',
url(r'^$', 'portal.views.home', name='home'),
url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
url(r'^logout/$', 'django.contrib.auth.views.logout'),
...
)
Any advice is much appreciated!
This app will do exactly what you need.

Resources