Currently I am working on a controller class which should be able to let a customer add an item to a table in a database and view these items (e.g. a movie).
I am using the following twig code:
{% extends 'base.html.twig' %}
{% block body %}
{% if movies|length == 0 %}
There are no movie items available. Add a movie here to get started.
{% elseif movies|length != 0 %}
These are the results: ...
{% endif %}
{% endblock %}
What is the best way to let a user/customer or whatever the case, add an item to the table that needs to be shown? Should I let a user fill a form on the exact same page as the overview template (I personally do not think this is good, as I want to keep purpose of each page seperated) or should I make a different template with a form where the user will be send to (though this takes redirection time, which some users might be getting annoyed by)? As you can see I am using an anchor tag on the word "here". How should I set-up the anchor tag if I am to use a different template for creating records in a table?
As the documentation of Symfony shows the following:
Home
The path says _welcome and I think it refers to the name of the route that points to a certain controller. Would it be best to use this path function and what would I need to add where it now says _welcome (or was I correct one sentence ago)? And why is there an underscore in the given example?
I am asking this question because when I worked with ASP.NET MVC, there was this method called ActionLink() and made me wonder if this is most common use of redirecting, since you could also just add the template file location to the anchor tag href attribute?
If the form to add a new item is small (one text field + one submit button), you could add the form in the same page.
For example :
{% extends 'base.html.twig' %}
{% block body %}
// display your form here
{% if movies|length == 0 %}
There are no movie items available.
{% elseif movies|length != 0 %}
These are the results: ...
{% endif %}
{% endblock %}
But actually it's up to you to decide if you want it to be displayed in the same page or not.
In the case you decide to redirect the user to a new template, especially for the form, you write the name of the route of the correspondant controller :
here
So the code of the controller will be executed and will redirect to the page of your form.
Concerning "_welcome", I don't know why they write it like this. This is more the way to name a layout file than a route name.
Related
I'm trying to make the trans('key' : value) method work by providing the variables either by PHP or preparing them on TWIG, both without any success so far.
So far I have tried to send the full line from the PHP Controller, which would be
{{bodymail| trans({'%user.name%': user.name,'%user.surname%': user.surname}) | raw}}
The following above works correctly when hard-coded, but when sending/composing it, it displays either the above code literally, or the correct message but without applying the translations.
This is something else I have tried, now on TWIG itself
{% set message = "'"~bodymail~"'| trans({" %}
{% for sub in variables %}
{% set message = message~"'%"~sub~"%': "~sub~"," %}
{% endfor %}
{% set message = message | trim (',', 'right') %}
{% set message = message~"}) | raw" %}
{{message}}
Code above is something I also tried for constructing the whole thing in TWIG itself... which resulted in directly not rendering the bodymail message (reference to .yml file).
Trying to make it work as a generic for anything that I input following the format (now i'm using user.name and user.surname, but I might want to use product references later for example).
EDIT: Doing some digging, and it looks like my problem stems from the fact that the form I'm creating builds off of the FOSUserBundle's registration form. Why is that an issue? Because while their RegistrationController throws a REGISTRATION_FAILURE event if the form isn't valid, it doesn't look like the event has a listener. So, the invalid state doesn't actually do anything aside from not being handled at all by the system. It doesn't even return the form (with errors).
I have a relatively simple form theme I want to use in order to display my form errors in a block at the top of my form:
{% form_theme form _self %}
{% block form_errors %}
{% spaceless %}
{% if errors|length > 0 %}
<div class="errors pt-2 mb-2">
<ul>
{% for error in errors %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endspaceless %}
{% endblock form_errors %}
I reference it in the form template with:
{% form_theme form 'Form/errors.html.twig' %}
And then I try to invoke it with a simple:
{{ form_errors(form) }}
But, when I intentionally provide incorrect data to my form inputs and try to submit, there's no error div present. The submission fails, due to there being 6 validation errors, but no errors are displayed/in the HTML source.
Looking at the documentation, I think I'm doing it right, but I'm obviously missing something.
You have two problems and you have to solve both of them in order to make the form validation work.
1st Problem:
First problem is that the listener is not working. If you intentionally make errors in the form data and the form validation is not kicking in, then you will never see the form_errors template. You have to go over the documentation for the FOSUserBundle.
First, check if you enabled/configured the validation.yml correctly.
Secondly, check the PHP class that generates the form. Make sure that the validation criteria are set properly.
Now, the most reliable way to check if the form is producing errors is to {{dump(form)}} in the Twig template. It will show all the data for the form, including the errors.
Keep working at it until you manage to see some errors. Otherwise you will not be able to do the next step.
2nd Problem:
The second problem is that you probably not including the correct template. I can not count how many times I had the same problem. You may have 3 or 4 templates that contain html/twig code for <form> but Symfony actually uses like 1 or 2 of them. Add your code to every one of them and make sure that your Twig block is not overridden by some other form block.
Also keep in mind that you have to clean both the app cache (php bin/console cache:clean -e prod) and the browser cache after every change in the templates. You might have done everything right and the damn cache is showing the cached results.
One last advice: use the browser developer tools. Often you find a lot of information and errors are shown in the tools' console.
what is the error of form?
For throwing error you have to set asserts on your entity.
for example:
class User extend baseUser
{
/**
* #Assert\NotBlank
*/
public $name;
}
for more information: https://symfony.com/doc/current/validation.html
I'm using UserFrosting and so far I've been able to import all of the default elements into the home page. However, I've now added a second page but nothing happened when I copied the following code from the home page:
{% include 'common/components/head.html' %}
<rest of code>
{% include 'common/components/main-nav.html' %}
<rest of code>
{% include 'common/components/footer.html' %}
{% include 'common/components/jumbotron-links.html' %}
I then used the following php code:
<?php include("../userfrosting/templates/common/components/head.html"); ?>
Which seems to work but the page only shows this code found within the head.html file:
{% for item in includeCSS(page_group|default("common")) %} {% endfor %} {% for item in includeJSTop(page_group|default("common")) %} {% endfor %}
Which obviously is not very useful!
When I keep the home and page2.php file in the same folder (in localhost/userfrosting/templates/common) then I receive Error 404. When I move the file to the default UserFrosting home page directory (which the home.html file isn't actually in) in localhost/public, I get only the above code.
It seems like I'm missing something quite basic here but would appreciate some help. Thanks.
You are confusing PHP files and template files. UserFrosting uses a front controller pattern along with the Twig templating engine. So, you do not need a separate PHP file for each page. Instead, you should create a new template file for your page:
userfrosting/templates/common/page2.html
{% include 'common/components/head.html' %}
// DO NOT use PHP here - just Twig! See the Twig documentation: http://twig.sensiolabs.org/doc/templates.html
{% include 'common/components/main-nav.html' %}
// More Twig
{% include 'common/components/jumbotron-links.html' %}
{% include 'common/components/footer.html' %}
Then you need to link up a URL with this template. That is done in the controller, public/index.php, for example like this:
// Miscellaneous pages
$app->get('/page2/?', function () use ($app) {
$app->render('common/page2.html', [
'page' => [
'author' => $app->site->author,
'title' => "Page Deuce",
'description' => "This is the second page, aight?",
'alerts' => $app->alerts->getAndClearMessages()
]
]);
});
I highly recommend going through the tutorial on adding a new page: https://learn.userfrosting.com/building-pages
You can also learn more about MVC, Slim, and Twig here: https://learn.userfrosting.com/basics/overview
Feel free to join in chat if you are still having trouble.
The Symfony 2.3 docs say that it is possible to customize global form errors (errors that appear at top of form that are not tied to a specific field).
http://symfony.com/doc/current/cookbook/form/form_customization.html#customizing-error-output
"You can also customize the error output for just one specific field type. For example, certain errors that are more global to your form (i.e. not specific to just one field) are rendered separately, usually at the top of your form..."
They go on to say that:
"To customize only the markup used for these errors, follow the same directions as above, but now call the block form_errors"
I am confused as to what they are talking about. It seems that their prior instructions already call the block "form_errors" so I am not sure what is different.
How do I customize just the global form errors (the individual form field errors should remain the same)?
The wording on that page is confusing. I had to read it a few times too, and it feels like there should be more information. The example provided shows how to check if the error is a "compound" error (for the whole form) or just an error for the individual field.
This is how my block looks:
{% block form_errors %}
{% if errors|length > 0 %}
<ul class="alert alert-warning {% if compound %}formError{% else %}formInputError{% endif %}">
{% for error in errors %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endblock form_errors %}
If it's a compound form, it renders the class as formError, and if it's just for an input it renders formInputError. That let's me style them slightly different, depending on if they appear at the top of the page or above an input. You could also make them completely separate HTML if you needed.
I want to achieve the following thing:
I have a basic template for all of my pages, named "_page_base.twig". It contains the header and footer.
Then I have a Template for different areas of the page: "topic.twig", "section.twig" and "article.twig" - each of them extending the "_page_base.twig", thats working well so far.
Now I want to write my articles. I would love to save them as .twig file as well, since I can edit the complete markup in my editor and just upload it.
Since I can't say that my article files just extend "article.twig" (multiple inheritance is not possible) I could tell the "article.twig" that it should use blocks from my different article-content twigfiles.
The problem is: "use" statements have to be hardcoded!
My current solution is to add {% use "[PLACEHOLDER]" %} into the "article.twig" and then loading the template into a string, replacing the placeholder to the correct article-content.twig and then passing the whole thing to the template engine. What a mess.
Have you guys any idea for a better solution?
You can try with include tag. Since this tag accepts a dynamic name template to include, you just only need to define a variable which contains the name of article twig template.
{# on article.twig#}
{% set articles = ['someArticle.twig', ...] %}
{% for article in articles %}
{% include article %}
{% endfor %}
{# on someArticle.twig #}
... Article text ...
In the case of you need to customize some content inside of someArticle.twig you could stage the next level: embed tag. You should define a block tag inside of someArticle.twig, this block will be the placeholder to the custom values.
{# on article.twig#}
{% set articles=['someArticle.twig', ...] %}
{% for article in articles %}
{% embed article %}
{% block inside_text_article %}
... custom text ...
{% endblock %}
{% endembed %}
{% endfor %}
{# on someArticle.twig #}
... article text ...
{% block inside_text_article %}default values{% endblock %}
... article text ...
https://github.com/fabpot/Twig/issues/17 - no dynamic namespaces
LiipThemeBundle might be a solution:
http://symfony2bundles.org/liip/LiipThemeBundle
Unless I am not understanding the question, displaying a single article only requires that it also extends __page_base.twig.
In the case that you would need to display multiple articles, you could have a template dedicated to showing a list of articles which would also extend __page_base.twig and pass the article list to this template.