XF 2.1 Javascript in foreach

Cupara

Well-known member
My problem is that I managed to get my date converted using Javascript but it only shows the converted date for the first entry. I have moved the code to my foreach and still same result.

Here is the template:
HTML:
<div>
                <ol class="block-body">
                    <xf:if is="$blizzPosts is not empty">
                        <xf:foreach loop="{$blizzPosts}" value="{$posts}">
                                <li class="block-row">
                                    <h4 class="node-title">
                                        <img src="/src/addons/GoblinTimes/BlizzardBlueTracker/icons/Wow.png" width="16px" /><span style="margin-left: 5px;" id="created_at"></span> -  {$posts.title}
                                    </h4>
                                    </li>
                                    <li class="block-row block-row--separated">
                                        <div class="contentRow">
                                            <div class="contentRow-figure">
                                            </div>
                                            <div class="contentRow-main">
                                                <ol class="block-body">
                                                </ol>
                                            </div>
                                        </div>
                                        <div class="contentRow">
                                            <div class="contentRow-main">
                                                <span style="color: #00AEE9">{$posts.excerpt}</span><br />
                                                    <a href="https://us.forums.blizzard.com/en/wow{$posts.url}">More Info...</a>
                                            </div>
                                        </div>
                                    </li>
                        </xf:foreach>
                    <xf:else />
                        <li class="block-row block-row--separated">
                            {{ phrase('gt_blizz_tracker_no_posts') }}
                        </li>
                    </xf:if>
                </ol>
                </div>
            </div>

Javascript:
HTML:
<script>
// Parsing date
    var v = '{$posts.created_at}';
    var d = new Date(v);
    var n = d.toLocaleString();
    document.getElementById("created_at").innerHTML = n;
</script>
 
Why not just use one of the template functions like {{ date($posts.created_at) }} ?

If you look in \XF\Template\Templater, you'll find the following functions you can use in templates:
  • date
  • date_from_format
  • date_dynamic
  • date_time
  • time
 
Those don't convert ISO 8601 formats so I am having to use Javascript.

So convert the dates in your view function or controller before displaying them?

I haven't worked with ISO 8601 dates, but I thought \DateTime::createFromFormat() could convert them? I would think that either the DateTimeInterface::ISO8601 or DateTimeInterface::ATOM formats would work (noting ISO8601 compatibility issues mentioned in https://www.php.net/manual/en/class.datetimeinterface.php#datetime.constants.iso8601)

If so, then you can use the date_from_format template function.
 
Try {{ date_from_format('c', $posts.created_at) }} ... I think the 'c' modifier does ISO 8601
 
Or alternatively, {{ date_from_format(DateTime::ISO8601, $posts.created_at) }} ... but I'm not sure if that will work
 
If all else fails - just do it manually {{ date_from_format("Y-m-d\TH:i:sP", $posts.created_at) }} I think it is (that's the ATOM format).

Do you have an example of one of your ISO 8601 dates that need to be formatted?
 
yeah saving I get an error using DateTime::ISO8601 but I tried the way you suggested as well and same thing, nothing displays.

Example:
HTML:
2019-12-17T00:01:14.363Z
 
ahh - that's not the format for ISO8601 that PHP understands since it contains milliseconds

You'll probably need to use {{ date_from_format("Y-m-d\TH:i:s.v\Z", $posts.created_at) }} (and be running PHP 7.0.0 or higher!)

Do the strings always end in Z (as in UTC time) or does that change based on people's timezone?
 
No it all ends in Z.

Also, I updated to that format but it still isn't showing.

HTML:
<div>
                <ol class="block-body">
                    <xf:if is="$blizzPosts is not empty">
                        <xf:foreach loop="{$blizzPosts}" value="{$posts}">
                                <li class="block-row">
                                    <h4 class="node-title">
                                        <img src="/src/addons/GoblinTimes/BlizzardBlueTracker/icons/Wow.png" width="16px" />{{ date_from_format("Y-m-d\TH:i:s.v\Z", $posts.created_at) }} -  {$posts.title}
                                    </h4>
                                    </li>
                                    <li class="block-row block-row--separated">
                                        <div class="contentRow">
                                            <div class="contentRow-figure">
                                            </div>
                                            <div class="contentRow-main">
                                                <ol class="block-body">
                                                </ol>
                                            </div>
                                        </div>
                                        <div class="contentRow">
                                            <div class="contentRow-main">
                                                <span style="color: #00AEE9">{$posts.excerpt}</span><br />
                                                    <a href="https://us.forums.blizzard.com/en/wow{$posts.url}">More Info...</a>
                                            </div>
                                        </div>
                                    </li>
                        </xf:foreach>
                    <xf:else />
                        <li class="block-row block-row--separated">
                            {{ phrase('gt_blizz_tracker_no_posts') }}
                        </li>
                    </xf:if>
                </ol>
                </div>
            </div>
 
try adding {{ dump($posts) }} to the top so you can see what the $posts variable actually contains.
 
The other vars in the template are working. If I just use {$posts.created_at} the date shows in the format I showed you. In the screenshot, the spot before the dash is where the date goes.
 

Attachments

  • Blizzard Blue Post Tracker   XenForo.webp
    Blizzard Blue Post Tracker XenForo.webp
    51.4 KB · Views: 9
Ahh - I just tested it, it seems that DateTime::createFromFormat does not support parsing milliseconds ('v' format), but it does support microseconds ('u' format) and will parse them into milliseconds as required.

So this format worked for me: "Y-m-d\TH:i:s.u\Z" when parsing your date
 
Ok thanks. Still not showing the date in it's converted format so I'm not sure why that is happening as I don't doubt the code you gave should work as written. Any ideas on what makes it not display at all?
 
Finally got a template error after I changed single quotes to double-quotes.

Error:
HTML:
Template public:gt_blizz_tracker: Object of class DateTime could not be converted to string (src/XF.php:931)

Format I have:
HTML:
{{ date_from_format("Y-m-d\TH:i:s.u\Z", $posts.created_at) }}
 
Top Bottom