Compare current item with previous in f:for loop [duplicate] - typo3

This question already has answers here:
Display list of elements grouped by year and by month in TYPO3 Fluid
(3 answers)
Closed 6 years ago.
I want to group my appointments by startDate (and later by lawyer.fullName).
So I want to display the appointment's startDate only if the previous appointment's startDate is different.
This is what I tried. But I really have no idea how I can get the object from the previous operation.
Line 3 is where the fail happens right now...
<f:widget.paginate objects="{appointments}" as="paginatedAppointments">
<f:for each="{paginatedAppointments}" as="appointment" iteration="i">
<f:if condition="{appointment.startDate->f:format.date(format:'d.m.Y')} != {0:paginatedAppointments.{i.index-1}.startDate->f:format.date(format:'d.m.Y')}">
<f:then>
<br/>
{appointment.startDate->f:format.date(format:'d.m.Y')}<br/>
{appointment.startTime->f:format.date(format:'H:i')}<br/>
{appointment.lawyer.fullName}<br/><br/>
</f:then>
<f:else>
{appointment.startTime->f:format.date(format:'H:i')}<br/>
{appointment.lawyer.fullName}<br/>
<br/><br/>
</f:else>
</f:if>
</f:for>
</f:widget.paginate>
Keep in mind if you have an answer: I would really like to keep using this useful paginate widget if possible.
--Edit--
I noticed that an answer from another question solved my question perfectly in terms of the grouping for DateTime objects so I marked my question as a duplicate. Thanks to Jigal's answer I found it, because I forgot about f:groupedFor.

You could create a ViewHelper with some value to compare as an argument that saves the startDate in a static variable and returns true/false if it is different from the last one. It is also useful if it has some kind of reset function, so something like that:
{vendor:utility.compareLast(reset:1)}
<f:for each="{paginatedAppointments}" as="appointment" iteration="i">
<f:if condition="{vendor:utility.compareLast(value:'{appointment.startDate->f:format.date(format:\'d.m.Y\')}')}">
...

Use the f:groupedFor viewhelper and you can group the items by startDate. In the inner loop you can check the iterator if it's the first and display the startDate in that case. See Fluid Guide

Related

TYPO3 Fluid items -> f:count() select field and f:widget.paginate

I currently have the following problem:
An item has different variables that I select simple via a select in the TCA. Now with my pagination widget I want to select only the elements that have this variable 1.
Of course, if I set a condition within the pagination, it does not work, because it calculates these into these pages (which suggests more pages than actually exists).
<f:if condition="{items -> f:count()} > 1">
<f:then>
<f:widget.paginate objects="{items}" as="paginatedItems" configuration="{itemsPerPage: 10, insertAbove: 0, insertBelow: 0, maximumNumberOfLinks: 10}">
<f:for each="{paginatedItems}" as="item">
<f:if condition="{item.variable} == 1">
<div>.....</div>
</if>
</f:for>
</f:widget.paginate>
</f:then>
<f:else>
You need to compute the pagination on the subselection in that way that you need to eliminate all unwanted records before you give the array of items to the pagination viewhelper.
Either you get this subselection directly from the repository (create a new query)
or you subselect the array of items into another fluid variable like it is done by ext:news (evaluation of already shown records)
I would prefer the first solution if possible as the performance should be better and it's scalable too.

How to make circle with break in fluid?

I want to stop my circle after output first element.
<f:for each="{errors}" as="error">
<f:switch expression="{error.code}">
<f:comment>The given subject was not a valid email address</f:comment>
<f:case value="1221559976">
<f:translate extensionName="helper" key="validator.emailaddress.notvalid" />
</f:case>
...
</f:switch>
BREAK????
</f:for>
Is it possible with fluid? Regards, Anton
You don't even need to iterate the collection, what for? Instead you can just fetch first element like: {errors.0}
Additionally if you want to fetch i.e. first 3 elements, you can prepare $limitedErrors (or smth) in your PHP controller and then assign it into the view.
It will be still more comfortable than manipulating within the template engine.
You can make you for each loop with additional argument iteration=""
add below code
<f:for each="{errors}" as="error" iteration="errorIterator">
and add condition
<f:if condition="{errorIterator.index} = 0">
or
<f:if condition="{errorIterator.isFirst}">
May you can use vhs viewhelper
<v:switch value="{variable}">
<v:case case="someValue" break="TRUE">
<!-- do whatever, if {variable} == 'someValue' -->
</v:case>
<v:case case="default">
<!-- the case "default" is a reserved keyword which acts as the default case. -->
</v:case>
</v:switch>
break > boolean

Extbase add calculated field in query/repository

I have a normal extbase extension.
In the controller I get all my records:
$stuff = $this->jobRepository->findAll();
$this->view->assign('stuff', $stuff);
and in the template I display them:
<f:for each="{stuffs}" as="stuff">
{stuff.title} <br />
{stuff.category}
</f:for>
Now I need a new field stuff.isnew with the value 1 if the record is the newest by category.
An SQL-Statement for that would look like:
SELECT j2.isnew, j.* FROM `tx_stuff_domain_model_stuff` as j
left join
(SELECT max(crdate) as crdate, category, 1 as isnew FROM `tx_stuff_domain_model_stuff` group by category) as j2
on j.crdate=j2.crdate and j.category=j2.category
(If I have to write my own Query I will have to check deleted, hidden, starttime, endtime to check if the record is active right now)
My question now is, what is the cleanest/best way to add that to my extension?
My solution would be to implement the method findAll in the job repository. It would first use the method findAll from the parent class to get all jobs. The usual constraints will already be applied. Then it would walk the resulting jobs and mark the newest one.
It should also be possible to create a custom query to reach you goal, but that would probably be a bite more work.
Actually you don't need to use additional query at all... while it's always first record which is new, you can just use an iterator of for ViewHelper:
<f:for each="{stuffs}" as="stuff" iteration="iterator">
<f:if condition="{iterator.isFirst}">THIS ONE IS BRAND NEW STUFF! </f:if>
{stuff.title} <br />
{stuff.category}
</f:for>

Access dynamic object property in Typo3 Fluid template

I have an object in a Typo3 Fluid template and want to access a property on it, but the name of the property is in a variable someProperty:
<f:if condition="searchObject.{someProperty}">
Found!
</f:if>
Because this does not work: Is there a built in way to access a property by variable?
You can give a chance to fedex Fluid viewhelper collection and its v:var.get viewhelper.
Or check the other viewhelpers in here. If you do not find a suitable one, you can write your own for this functionality based on some example here.
UPDATE:
Since this is an old question to TYPO3 6.2 it is the time to update it to the current standards. (See also the answer of Claus Due:
For the current LTS: TYPO3 9.5, you can use simple:
{searchObject.{someProperty}}
In Fluid standalone and TYPO3v8 and upward:
{array.{variableContainingKey}}.
The point notation actually is the correct way to access a property. What do you mean by dynamic? Can be null? Have you tried the following?
<f:if condition="<f:count>{searchObject.someProperty}</f:count>">
Found!
</f:if>
Or maybe just:
<f:if condition="{searchObject.someProperty}">
Found!
</f:if>

jquery .html() returning null in ie7

On click li element i am getting the current element value and appending it into another div dynamically.Its working fine in all browsers.But returning null in IE7.I don`t the reason that why its happening?Please can any one give me a solution for this..Part of the code only i pasted here.
Sample code:
////////////.//This line returning null in IE7./////////////////
$('#pagelink_a #pagelinkli_'+tab_lastid_val).html()
(tab_lastid_val value can be a 1 or 2 or 3.Clixked li element value comes here)
<div class="pagelink">
<div id="pagelink_a">
<ul>
/******** all li element are clickable***********/
<li id="pagelinkli_1"><a>Google</a></li>
<li id="pagelinkli_2"><a>Chrome</a></li>
<li id="pagelinkli_3"><a>Firefox</a></li>
</ul>
</div>
</div?
try this:
$('#pagelink_a').find('li[id=pagelinkli_'+tab_lastid_val']').html();
code is not tested but i think it should work.
Given your html layout, your parent div is .pagelink not #pagelink_a , so replace your following line:
$('#pagelink_a #pagelinkli_'+tab_lastid_val).html()
for this one:
$('.pagelink #pagelinkli_'+tab_lastid_val).html()
Just use
$('#pagelinkli_'+tab_lastid_val).html()
The # tag identifies an ID which only a single element may have. There is no need to have anything preceding it. You also labeled the previous class as id, which is wrong. I don't know how your other browsers managed to get anything.
Although bit off topic, it may be better to actually drop IE7 support entirely. Due to small user base and decreasing popularity, it may be costing you more money by support it than to not support it.
Try instead of html() , and try append().
For example
$('#ID').append('Your content');