I am making some small project with Symfony, but now I have a question about base.twig.html, and does it should be passed with some entity in it. I am using Symfony 4.
Lets say I have some entity MainCategory with:
id
name
info
slug
Then from my Route /, I use MainCategoryRepository to get all records for that entity, then render the base.twig with the passed records.
Then in navigation bar, I loop over all records and make links with the entity.name.
After that in another Route "/{slug}", i render another twig file which extends the base one. But here i am not using the repository, i use just the Entity - MainCategory, because the 'slug' is unique field and it will get only that record.
And here is the problem, i am just passing one record, but the navigation bar from the 'base.twig' loop over all records and here I get an error:
Variable "mainCategories" does not exist.
Here is my code:
Route "/"
/**
* #Route("/", name="app_homepage")
*/
public function homepage(MainCategoryRepository $mainCategoryRepository)
{
$mainCategories = $mainCategoryRepository->findAll();
return $this->render('base.html.twig', [
'mainCategories' => $mainCategories,
]);
}
"base.html.twig"
{% for mainCategory in mainCategories %}
<li>
<a href="{{ path('category_show', {'slug': mainCategory.slug}) }}">
{{ mainCategory.name }}</a>
</li>
{% endfor %}
Route "/{slug}"
/**
* #Route("/{slug}", name="category_show")
*/
public function categoryShow(MainCategory $mainCategory)
{
return $this->render('show.html.twig',
[
'mainCategory' => $mainCategory,
]
);
}
"show.html.twig"
{% extends 'base.html.twig' %}
{% block body %}
<p>{{ mainCategory.Info }}</p>
{% endblock %}
ERROR:
Variable "mainCategories" does not exist.
So it is good idea to pass any entity in base.twig? I can pass all records in the second twig file, but that means I have to do it in every template which extends the base.twig.
I found one solution, dont know is it perfect or the right solution, but it works.
I made one Service with a method in which I return all records from MainCategory Entity.
MainCategoryLoaderService
protected $mainCategoryRepository;
public function __construct(MainCategoryRepository $mainCategoryRepository)
{
$this->mainCategoryRepository = $mainCategoryRepository;
}
public function getAllMainCategories()
{
return $this->mainCategoryRepository->findAll();
}
Then in the file config/packages/twig.yaml I made one global variable:
Global Variable
globals:
globalMainCategory: '#App\Service\MainCategoryLoaderService'
After that in base.html.twig I made one variable in which I will have all main categories:
Twig Variable
{% set mainCategories = globalMainCategory.getAllMainCategories() %}
And then just loop over that variable.
Related
I am sorry if the title is poorly phrased, but what i am trying to do is to use a variable that was in a for loop outside of it's scope ( in another part of the template )
here is my template:
<div class="inventory-content">
<div class='category'>
<div>Categories</div>
<div class='category-checkbox'>
{%for category in items%}
<input type="checkbox" id="{{category.id}}" name="{{category.name}}" value="{{category.id}}">
<label for="{{category.name}}"> {{category.name}}</label><br>
{%endfor%}
</div>
</div>
<div class='items'></div>
</div>
<script>
$('.category-checkbox input[type="checkbox"]').click(function() {
if ($(this).is(':checked')) {
// Add the element to the div with an id identifier
$('.items').append(`<div id="item_${this.id}">123</div>`);
} else {
// Remove the element from the div targeted by the id identifier
$(`#item_${this.id}`).remove();
}
});
</script>
the view.py
def index(request,pk):
vessel_id = Vessel.objects.get(id=pk)
categories = vessel_id.category.all()
item = categories.prefetch_related(
'items')
context ={"vessel_id":vessel_id,'items':item}
return render(request,'inventory.html',context)
i want to be able to use that category variable so i can loop through all the items in that specific category and add them in the items <div>, if there is a better way to do this please guide me !
Replace click with on event as you are dynamically adding elements like this:
$('.category-checkbox input[type="checkbox"]').on('click', function() {
// rest of your code
});
Our users have the usual CRUD actions in various flask pages.
For one scenario, the Create action can be an intensive process, with lots of domain logic performed, and on occasion, items have been created accidentally.
Our users would now like to add a simple "Are you sure you want to create this Account?" prompt when they click the "Save" button. The next response would simply be Yes and No buttons.
It's not apparent how to add this - are we missing something obvious?
Override the Flask-Admin create template for the particular view and add a JavaScript confirmation to the form's onSubmit event. Adding the confirm to the submit event handles the three submit buttons; 'Save', 'Save and Add Another' and 'Save and Continue'.
For example:
class UserView(ModelView):
create_template = 'create_user.html'
# ...
In the /templates/admin folder add html file 'create_user.html':
{% extends 'admin/model/create.html' %}
{% block tail %}
{{ super() }}
<script src="{{ admin_static.url(filename='admin/js/helpers.js', v='1.0.0') }}" type="text/javascript"></script>
<script>
(function ($) {
$('form:first').on('submit', function() {
return faHelpers.safeConfirm('{{ _gettext('Are you sure you want to save this record?') }}');
});
})(jQuery);
</script>
{% endblock %}
Note there's a bug in Flask-Admin 1.5.3, helpers.js is missing from the distribution and you will need to add the safeConfirm function.
{% extends 'admin/model/create.html' %}
{% block tail %}
{{ super() }}
<script>
(function ($) {
function safeConfirm(msg) {
try {
var isconfirmed = confirm(msg);
if (isconfirmed == true) {
return true;
}
else {
return false;
}
}
catch (err) {
return false;
}
}
$('form:first').on('submit', function () {
return safeConfirm('{{ _gettext('Are you sure you want to save this record?') }}');
});
})(jQuery);
</script>
{% endblock %}
I'm trying to figure out the collective's checkbox function.
Here are the code in the blade template:
{{ Form::model($record, ['route' => ['access_record.update', $record->id], 'method' => 'put']) }}
{{ Form::checkbox('IsApprove', 1, true) }}
{{ Form::submit() }}
{{ Form::close() }}
as you see, I set up the checkbox named: IsApprove and give it the default value. However, I can not receive any value from pages.
Here are the codes in the controller's update function:
public function update(Request $request, $id)
{
$record = Accessrecord::find($id);
print_r($request->toArray());
}
And there is nothing to print out.
How do I make the collective's checkbox retrieve value?
Thanks!
I guess I find out the answer. It seems my apache server got crush. After restart apache server, it fixed.
I have a Django template that displays a link generated with template tags, and I want to send it as a context variable:
views.py:
def my_view(request):
...
link = '''Drop'''
context = {
'link': link,
}
return render(request, "my_template.html" , context)
I am trying this in my_template.html:
{{ link | safe }}
but the link is literally rendered as "{% url 'quests:drop' s.id %}"
Is there a way to have the template tags sent in the context variable recognized and executed by the template engine?
EDIT:
Why I am trying to do this is because I will actually be sending a list of buttons to the template, each with a different link and text, which will be looped through (in this example, looping through various 's' objects), and multiple views will be using the template (each view with their own button set), so the buttons are extremely context specific.
My template was becoming a spaghetti of logic to handle all the situations, and sending the buttons in the context seems like it would be much more DRY and result in a cleaner, easier to read template.
EDIT 2:
Another option that could solve the problem is if I could just pass the changing parts:
link_data = ['quests:drop','Drop']
context = {
'link_data': link_data,
}
return render(request, "my_template.html" , context)
And then the template would have:
{{link_data.1}}
However, as is, {{link_data}} doesn't render and I get the error:
Reverse for '{{ link_data.0 }}' ... not found.
You shouldn't is the answer. To achieve what are trying to do fits perfectly inline with how templates are supposed to work and you are over complicating it.
context = {
'buttons': {
'button1': {
'text': 'This is a button',
'link': reverse('quests:drop', args=[...])
},
'button2':{...}
}
}
And in the template:
{% for button in buttons %}
<a class="btn btn-primary" href={{button.link}}>{{button.text}}</a>
{% endfor %}
You could also create a Button class and use it similarly:
context = {
'buttons': [
Button('This is text', reverse('quests:drop', args=[...]),
...
],
}
Referencing to your 2nd edit:
The code in your template should look like this:
{{ link_data.1 }}
Notice the omitted '{{ }}' tags.
I'm trying to customize form labels that are generated in subforms.
I want to display soccer fixtures that are contained in a specific game week, like the following:
- Fixture 1 : Manchester United (0) - (1) Arsenal
- Fixture 2 : Chelsea (2) - (1) Liverpool
- ...
My form displays all fixtures and related scores but all labels contain the database column names (score1, score2). I want to put team names instead.
So, it currently shows:
- Fixture 1 : score1 (0) - (1) score2
- Fixture 2 : score1 (2) - (1) score2
- ...
In the controller, I generate the week form (WeekType). $week contains week data and fixtures data using $week->getFixtures().
Controller/DefaultController.php
$form = $this->createForm(new WeekType(), $week)->createView();
return array(
'form' => $form,
);
Form/WeekType.php
class WeekType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('fixtures', 'collection', array(
'type' => new FixtureType(),
));
}
}
The Fixture form adds 2 fields. I want to replace default labels into team names.
However I cannot access fixture data in this form. $options is NULL. I thought $options['data'] would contain fixtures data... but I was wrong.
Form/FixtureType.php
class FixtureType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('score1', 'text', array('label' => **WHAT TO PUT HERE**));
$builder->add('score2', 'text', array('label' => **WHAT TO PUT HERE**));
}
}
I display all fixtures using this code, and it works great.
index.html.twig
{% for fixture in week.form.fixtures %}
{{ form_widget(fixture) }}
{% endfor %}
Maybe I could customize my labels directly in index.html.twig but how can I get fixtures data?
Does somebody encounter this issue and resolve it?
I found a solution!
In "index.html.twig" template, I iterated over form elements.
It was a mistake. I just had to iterate over fixtures and get related form widget.
index.html.twig
{% for fixture in week.fixtures %}
fixture.HomeTeam.name
{{ form_widget(week.form.fixtures[loop.index0]) }}
fixture.AwayTeam.name
{% endfor %}
The trick is to retrieve form elements directly from form widgets array :
week.form.fixtures[loop.index0]
http://symfony.com/doc/current/book/forms.html#rendering-each-field-by-hand
use
{{ form_label(fixture) }} <- {{ team.name }}
{{ form_errors(fixture) }}
{{ form_widget(fixture) }}
instead of
{{ form_widget(fixture) }}