JSReport & Handlebars IF value is int - handlebars.js

Have been struggling with JSreport couple hours today making PDF report for my app. Now met the problem in if statement, where I need to compare index number to integer.
In Javascript I can compare like this if (partKey === 6), but with handlebars this is not working and I'll tried these with no luck:
{{#each computer.parts as |part partKey|}}
<div class="item">
<span>{{ part.productName }}, {{ part.weight }}g</span><br></br>
{{ #if (eq partKey 6) }}
<div style="page-break-before: always"></div>
{{ /if }}
</div>
{{/each}}
I just want to change page after six objects. Also tried these; {{ #is partKey 6 }}, {{ #if_eq partKey 6 }}, {{ #equals partKey 6 }}.
Any ideas which should work?
If i print partKey like this {{ partKey }} it prints nicely. When I try to use it in if it gives a parse errpr, says partKey is Invalid.

Related

Hugo: how can I add a class for the last post?

I'm using this baseof.html to add the class of first-post to the body tag so that I can use specific CSS on the first post of a series of posts which are paginated:
<body class="
{{ with where site.RegularPages "Type" "posts" }}
{{ $first_post = index . 0 }}
{{ if eq $first_post $ }}
first-post
{{ end }}
{{ end }}
">
But how can I add a class for the last post? With this, I get the error “can’t iterate over *hugolib.pageState”:
<body class="
{{ with where site.RegularPages "Type" "posts" }}
{{ $last_post := last 1 $ }}
{{ if eq $last_post $ }}
last-post
{{ end }}
{{ end }}
">
Docs for last: https://gohugo.io/functions/last/
LE: I've re-read you're question and realised I had misunderstood your aim, initially. I've redone the answer, hopefully I got it right this time around.
For adding a CSS class to an item while iterating them, i.e. displaying multiple on the same page, I kept the old answer below.
For adding a class on an item's own page, depending on its position in the global list, try this.
The list & the sorting
Round up the items in $allPosts. By default, I think they are sorted by .Date, descending, i.e. newest first. To force your own order or criteria, you can use sort.
{{ $allPosts := where site.RegularPages "Type" "posts" }}
{{ $allPostsByDate := sort $allPosts ".Date" "asc" }}
The pages of interest
Get whichever items are special. For the first and the last, you can use their respective built-in functions; both first and last return arrays with one element (the page, in this case), so to extract the one element, you can use index.
{{ $firstPost := index (first 1 $allPostsByDate) 0 }}
{{ $lastPost := index (last 1 $allPostsByDate) 0 }}
Compare with the current page
All the code in this example must be included in a template like single.html, which runs for each page. So, for each page that is rendered, you have one last check to make, to see whether the current page is one of the special ones.
I don't know Hugo that well to say if there's a better way of comparing two pages, but .Permalinks seem good enough.
{{ if eq $firstPost.Permalink $.Permalink }} first-post {{ end }}
{{ if eq $lastPost.Permalink $.Permalink }} last-post {{ end }}
The whole thing
With the whole list displayed, for visualising what's what.
{{ $allPosts := where site.RegularPages "Type" "posts" }}
{{ $allPostsByDate := sort $allPosts ".Date" "asc" }}
{{ $firstPost := index (first 1 $allPostsByDate) 0 }}
{{ $lastPost := index (last 1 $allPostsByDate) 0 }}
{{/* on the single page */}}
{{ .Title }} —
{{ if eq $firstPost.Permalink $.Permalink }} first-post {{ end }}
{{ if eq $lastPost.Permalink $.Permalink }} last-post {{ end }}
<br><br>
{{/* on a list */}}
{{ range $allPostsByDate }}
{{ .Title }}
{{ if eq $firstPost.Permalink .Permalink }} first-post {{ end }}
{{ if eq $lastPost.Permalink .Permalink }} last-post {{ end }}
<br>
{{ end }}
Old answer
Using Hugo last
I think there might be a typo there? I can't test now, but I would say that you need to have a dot instead of a question mark. I don't know what the $ variable is, if it's something in Hugo. In fact, that would explain the error. last expects the second argument to be an array, and you're giving it a PageState. So it should probably be something like this:
{{ $last_posts := last 1 . }}
{{/* This will give you an array of length 1, over which you then have to iterate. */}}
{{ $last_post := index $last_posts 0 }}
{{/* or */}}
{{ range $last_posts }}
{{/* last post here */}}
{{ . }}
{{ end }}
Using Hugo len
Following the same pattern, you could get the last index via the array's length. Hugo's len function
{{ $last_index := (len .) - 1 }}
{{ last_post := index . $last_index }}
Using CSS
You can drop the custom treatment for the first and last posts altogether from the templates, and use CSS pseudoclasses, like
:first-child()
:last-child()
So your posts wrapper can have a .posts CSS class, and then, in your stylesheets, you can have something like
.posts:first-child {
/* first post, make it pop */
border-top: 1px dashed red;
}
.posts:last-child {
/* last post, make room */
border-bottom: 1px dashed black;
}
This way, however, you shift the computation over to the client. I don't really think it's that intensive a computation, especially with only a first/last, but it's something to consider.

Symfony not rendered form fields put to Null

I have a form that has let's say : formField1, formField2, ... formField10.
In my twig view, I want the 5 first form fields to be displayed.
My code looks like something like this :
{{ form_widget(form.formField1, {'attr': {'class': 'form-control'}}) }}
{{ form_widget(form.formField2, {'attr': {'class': 'form-control'}}) }}
{{ form_widget(form.formField3, {'attr': {'class': 'form-control'}}) }}
{{ form_widget(form.formField4, {'attr': {'class': 'form-control'}}) }}
{{ form_widget(form.formField5, {'attr': {'class': 'form-control'}}) }}
So when I submit this, it's fine for those fields : everything works fine in the databse.
But for the other fields (6 to 10), my database shows "NULL" for everything...
So my solution for now is to do this :
<div class="form-group hidden">
<div class="col-md-10 col-sm-9 col-xs-12">
{{ form_rest(form) }}
</div>
</div>
But it's not very safe (F12 + remove hidden property :))
Any idea how NOT to touch those other fields ?
I tried to disable them too :
{{ form_widget(form.formFieldX, {'attr': {'class': 'form-control'}, 'disabled': true}) }}
but it doesn't work either (set to NULL).
The only safe solution is to exclude these fields from the form type (for example by adding options to turn them on/off under certain conditions).
The Form component, by default, clears (i.e. sets them to null) all form fields that are part of the form type, but not of the request. This can be turned off, but this option is rather meant to allow support for HTTP PATCH requests. Furthermore, if you still kept the fields in your form type, your users could as well manually add the needed HTML code for it and submit them meaning they would again be changed.

twig form multiple block in symfony4

I have a form with block of the different input field.
When I use, standard twig function I get one block:
{{ form(form) }}
If I want to change something inside form I use, for example:
{{ form_start(form) }}
{{ form_widget(form.firstName) }}
{{ form_widget(form.lastName) }}
{{ form_end(form) }}
And everything is fine with this, but here I use JS for adding multiple block of the same field in the form (like can be possible to add multiple person in one form). When I want to edit data, I catch all data from the DB, of course, and want to show blocks in the twig.
{{ form_start(form) }}
{# somehow start loop data from the DB here #}
<div class='block'>
{{ form_widget(form.firstName) }}
{{ form_widget(form.lastName) }}
</div>
{# somehow end loop data from the DB here #}
{{ form_end(form) }}
Is it possible in the Twig, or I should use old school here?
For all who google for same question, answer is here:
http://symfony.com/doc/current/form/form_collections.html

Symfony : easy way to format FORMS with CSS?

We're building a web site with Symfony 2. We generate a unique URL and send it by email to user who forgot their password, so they can reset their password.
We're building a simple form to reset a password. We have two labels ('Enter your new password' and 'Enter your new password again') with a textbox beside each.
We wanted the textbox to align with each other.
Lazy solution was to figure out two strings of the same length (!)
But I would have wanted to format them with CSS or put them in a table ...
Is that possible at all with Symfony's form ? I read documentation about customizing templates, but when we tried the solution proposed by Symfony's docs the widgets (textboxes) were not rendering ...
Here are some pics of the issue :
Crooked textboxes
Lazy solution
Here is the code of the twig where I think(!) the formatting should be done
{% block blockPrincipal_mp %}
<h1>{{ titre }}</h1>
{{ form_start(form) }}
<div class="containerForm">
<div class="error">
{{ form_errors(form) }}
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
{% for flashMessage in app.session.flashbag.get('success') %}
<div class="confirm"><p> {{ flashMessage }}</p></div>
{% endfor %}
</div>
{% endblock %}
You can render all the different elements of the forms individually as opposed to just rendering it all at one time with form_rest(form) as you have in your example. form_rest() is going to render whatever hasn't been rendered yet. And up to this point, All that's been rendered are the errors.
I don't know what your form property's names are but here's an example:
{{ form_start(form) }}
<div class="form_errors">{{ form_errors(form) }}</div>
{# output all pieces of the username element individually #}
<div class="form_label">{{ form_label(form.username) }}</div>
<div class="form_input">{{ form_widget(form.username) }}</div>
<div class="form_errors">{{ form_errors(form.username) }}</div>
{# output all pieces of the password element individually #}
<div class="form_label">{{ form_label(form.password) }}</div>
<div class="form_input">{{ form_widget(form.password) }}</div>
<div class="form_errors">{{ form_errors(form.password) }}</div>
{{ form_rest(form) }}
{{ form_end(form) }}
This way you can control what HTML wrappers surround each piece of your form elements.
Note that you can also output the username and password fields by doing...
{{ form_row(form.username) }} {{ form_row(form.password) }}
...and it will still output the label, widget and errors but will use the default layout for those form types that is defined in your twig templates. So you have more control of rendering the parts if you do them individually.
This is great for custom forms and custom templates, however you can also override the default form element's layout if you want more control over how individual form elements are rendered throughout your site, by extending the form fields template.
https://symfony.com/doc/current/form/form_customization.html
The RepeatedType field can be dispayed separately:
{{ form_row(form.password.first) }}
{{ form_row(form.password.second) }}
or more controlled:
{{ form_label(form.password.first) }}
{{ form_widget(form.password.first) }}
{{ form_label(form.password.second) }}
{{ form_widget(form.password.second) }}

How to assign class to invalid Symfony 2 form field, rendered with Twig?

Lets assume that few fields values of my form, build on Symfony 2 and rendered with Twig are not valid and I received validation errors. I want not only to see this errors, but also assign special class to each invalid field.
For example:
<input type="text" class="error">
How can I do that? As I understand, there is need to redeclare my form template. Is there any working example how to assign attributes in case of concrete field validation failure.
All I found now, is that I need to set this class in form template:
{% set attr = attr|merge({'class': attr.class|default('') ~ (errors|length > 0 ? ' error' : '') }) %}
But what I don't understand is how to specify exact field? Any help appreciated.
This works for me:
<div class="input{{ form_errors(form.expiry) == '' ? '' : 'error' }}">
{{ form_widget(form.expiry) }}
</label>
You could also do
{{ form_widget(form.expiry, {'attr': {'class': form_errors(form.expiry) == '' ? '' : 'error'}}) }}
If you use
{{ form(form) }}
for showing your form, I am quite sure you can not accomplish what you want, or at least I am not aware of the possiblity.
If you use something like this
{{ form_row(form.task) }}
{{ form_row(form.dueDate) }}
I am still quite sure you can not get what you want.
My solution for what you need would be to make something like this:
{{ form_start(form) }}
{{ form_errors(form) }}
<div>
{{ form_label(form.task) }}
{{ form_errors(form.task) }}
{{ form_widget(form.task) }}
</div>
<div>
{{ form_label(form.dueDate) }}
{{ form_errors(form.dueDate) }}
{{ form_widget(form.dueDate) }}
</div>
<input type="submit" />
{{ form_end(form) }}
and to simply get information about validation errors from form object and then to replace {{ form_widget(form.task) }} with something like this
{{ form_widget(form.task, {'attr': {'class': 'error'}}) }}
in case that field task failed the validation.
Even more slow and time consuming solution would be to make small twig files that each and every one would actualy represent "your" design for view of each form field and then to call those "little twigs" with an argument which would again come from form object which contains those data about bad validation.
You can read more about form rendering where you actualy make your own form field designs here
http://symfony.com/doc/current/cookbook/form/form_customization.html

Resources