In Silverstripe template I need to compare variable $date_ok with current date like this : if($date_ok < date("j, n, Y") {...};
<% loop $IzdMat %>
<tr>
<td>$num</td>
<td>$sert_otip </strong> <br>Valid from $date_start till
$date_ok</td>
<% if $date_ok < ****** %>
..............
<% end_if %>
.......
What I have to write insted of ****** ?
You can add a method to the DataObject rather than trying to do complicated logic in the templates. This is assuming that date_ok is a date field defined in the $db array.
class IzdMat extends DataObject {
public function IsDateOk() {
$today = date("Y-m-d");
return (strtotime($today) < strtotime($this->date_ok));
}
}
Then in your template.
<% loop $IzdMat %>
<tr>
<td>$num</td>
<td>$sert_otip </strong> <br>Valid from $date_start till
$date_ok</td>
<% if $IsDateOk %>
..............
<% end_if %>
</tr>
<% end_loop %>
Related
I'm banging my head trying to figure this out and I feel like I'm over thinking it.
So I've built 2 DataObjects (Brand, Product) and 1 Controller/Page (ProductType).
ProductType has many Products
Product has one Brand
Product has one ProductType
Brand has many Products
What I'm looking to do is:
ProductType pages should make available a list of Brands that are used ONLY by the Products of that Type.
Now I have one somewhat working but it feels hacky and not very portable. Example below:
ProductType Controller:
public function getBrands() {
if($products = $this->Products()) {
$group = GroupedList::create($products->sort('BrandID'))->GroupedBy('BrandID');
}
}
Product Type Template:
<% if Brands %>
<ul>
<li>All</li>
<% loop Brands %>
<% loop Children.Limit(1) %>
<li>$Brand.Title</li>
<% end_loop %>
<% end_loop %>
</ul>
<% end_if %>
Is there a way I can build a method in the ProductType controller that would return a DataList of just the Brands used by Products of that type?
Using Silverstripe 3.1.3
Let me know if I need to be more clear about something and thanks!
Ah, i guess you had a misunderstanding of a GroupedList
You already have the Datalist of all products of this product type.
It's the has_many relation
$this->Products()
now you want to group the current products by BrandID. Your method naming might be confusing, so let's rename it a bit:
public function getProductsGroupedByBrands() {
if($products = $this->Products()) {
$group = GroupedList::create($products->sort('BrandID'))
->GroupedBy('BrandID');
}
}
So in your template you have a GroupedList you can loop over.
<% if Products %>
<ul>
<li>All</li>
<% loop ProductsGroupedByBrands %>
<li>
<%-- here you should be able to see the grouping relation --%>
$Brand.Title
<%-- in doubt use the First element to get the current Brand, it's a has_one -->
<% with $Children.First %>
$Brand.Title
<% end_with %>
<ul>
<% loop Children %>
<%-- here are the products grouped by brand --%>
<li>$Title</li>
<% end_loop %>
</ul>
</li>
<% end_loop %>
</ul>
<% end_if %>
See also Silverstripe Docs or Grouping Lists
Hi I'm using silverstripe 2.4.7 and I'm having difficulty getting the pagination to work. I've created a function in my page.php to get the latest articles like so
function AllNewsPosts($num=1) {
$news = DataObject::get_one("NewsHolder");
return ($news) ? DataObject::get("NewsEntry", "ParentID > 0", "Date DESC", "", $num) : false;
}
Then when i put this function into the control and pagination tags one article shows up however the links to the concurrent articles do not work - essentially the pagination is not working and I'm not sure how to fix it
<% if AllNewsPosts %>
<% control AllNewsPosts %>
<div class="event">
<h2>$MenuTitle |<span class="date"> $Date.Time $Date.Long</span></h2>
<p>$Content.FirstParagraph</p>
See more about this event
</div>
<% end_control %>
<% else %>
<div class="no-entry">'There are no entries'</div>
<% end_if %>
<% if AllNewsPosts.MoreThanOnePage %>
<div id="PageNumbers">
<p>
<% if AllNewsPosts.NotFirstPage %>
<a class="prev" href="$AllNewsPosts.PrevLink" title="View the previous page"><span class="yellow-background">Prev</span></a>
<% end_if %>
<span>
<% control AllNewsPosts.PaginationSummary(0) %>
<% if CurrentBool %>
<span class="current">$PageNum</span>
<% else %>
<% if Link %>
$PageNum
<% else %>
…
<% end_if %>
<% end_if %>
<% end_control %>
</span>
<% if AllNewsPosts.NotLastPage %>
<a class="next" href="$AllNewsPosts.NextLink" title="View the next page"><span class="yellow-background">Next</span></a>
<% end_if %>
</p>
</div>
<% end_if %>
Any help is much appreciated
Note: The following answer is for Silverstripe 2.4. This should not be used for Silverstripe 3.0+ sites. From 3.0 and onwards the PaginatedList object makes pagination much easier.
You are not setting a limit on how many entries to retrieve in your query, or where to start from.
The following tutorial explains how to apply pagination to a set of data objects exactly as you are trying to do:
http://www.ssbits.com/tutorials/2010/paginating-a-filtered-dataobjectset/
Here is an attempt at altering your function to include limit and start as needed for pagination:
PHP
function AllNewsPosts() {
if(!isset($_GET['start']) || !is_numeric($_GET['start']) || (int)$_GET['start'] < 1)
{
$_GET['start'] = 0;
}
$SQL_start = (int)$_GET['start'];
$newsEntries = DataObject::get('NewsEntry', '', 'Date DESC');
$doSet = new DataObjectSet();
foreach ($newsEntries as $newsEntry) {
if ($newsEntry->canView()) {
$doSet->push($newsEntry);
}
}
$doSet->setPageLimits($SQL_start, 10, $doSet->Count());
return $doSet;
}
Note the above will display 10 items per page. You can change this to however you need per page.
can one inside a loop in template over a DataObject somehow tell wether you're at $Pos 24 but counted from bottom - something like:
<% if Pos = "-24" %>do stuff<% end_if %>
or like
<% if TotalItems - 24 = Pos %>do stuff<% end_if %>
or like
<% if Last(24) %>do stuff<% end_if %>
In Silverstripe 3, to be able to do:
<% if FromBottom(24) %>
Hello
<% end_if %>
you'll have to add MyCustomIteratorFunctions.php to your /code folder with the following contents:
<?php
class MyCustomIteratorFunctions implements TemplateIteratorProvider
{
protected $iteratorPos;
protected $iteratorTotalItems;
public static function get_template_iterator_variables()
{
return array('FromBottom');
}
public function iteratorProperties($pos, $totalItems)
{
$this->iteratorPos = $pos;
$this->iteratorTotalItems = $totalItems;
}
function FromBottom($num)
{
return (($this->iteratorTotalItems - $this->iteratorPos) == $num);
}
}
as seen here: https://groups.google.com/forum/#!msg/silverstripe-dev/DVBtzkblZqA/PWxanKGKDYIJ
Using Silverstripe's "ChildrenOf" syntax, I've been successfully able to list all children of a page's parent. It's being used in a "see also" style list on a page.
I'd like to exclude the current page from the list but unsure how to determine which is the same as the current page, as within the control loop I'm in the parent's scope. Any ideas? Here's a pseudocode of what I'm doing:
<% control ChildrenOf(page-url) %>
<!-- Output some stuff, like the page's $Link and $Title -->
<% end_control %>
there's a built-in page control for this, so to exclude the current page from your list:
<% control ChildrenOf(page-url) %>
<% if LinkOrCurrent = current %>
<!-- exclude me -->
<% else %>
<!-- Output some stuff, like the page's $Link and $Title -->
<% end_if %>
<% end_control %>
see http://doc.silverstripe.org/sapphire/en/reference/built-in-page-controls#linkingmode-linkorcurrent-and-linkorsection
UPDATE
as you mentioned in your comment below that you'd like to use the $Pos control, you need to filter the dataobjectset before iterating over it.
add the following to your Page_Controller class:
function FilteredChildrenOf($pageUrl) {
$children = $this->ChildrenOf($pageUrl);
if($children) {
$filteredChildren = new DataObjectSet();
foreach($children as $child) {
if(!$child->isCurrent()) $filteredChildren->push($child);
}
return $filteredChildren;
}
}
then replace 'ChildrenOf' in your template by 'FilteredChildrenOf':
<% control FilteredChildrenOf(page-url) %>
//use $Pos here
<% end_control
In Silverstripe 3.1 you can use a method like this -
<% loop $Parent.Children %>
<% if $LinkingMode != current %>
<!-- Output some stuff, like the page's $Link and $Title , $Pos etc -->
<% end_if %>
<% end_loop %>
This way you can list all parent's children pages.
See https://docs.silverstripe.org/en/3.1/developer_guides/templates/common_variables/
Can we set an id attribute as I would for something like a table column via:
for an html dropdown list element that is created with a helper such as:
<% for (int i = 0; i < Model.Trx.TransactionHolidayCityCollection.Count; i++)
{%>
<%= i > 0 ? "," : "" %>
<%= DropDownData.HolidayDays().ToList().Find(item => item.Value == Model.Trx.TransactionHolidayCityCollection[i].HolidayCityID.Value.ToString()).Text %>
<%} %>
You don't need a helper, necessarily:
<select id="holidayCities" name="holidayCities">
<% foreach (HolidayCity city in Model.Trx.TransactionHolidayCityCollection) { %>
<option
value="<%=city.HolidayCityID.Value %>"
id="holidayCity_<%=city.HolidayCityID.Value %>"
><%=city.Name %></option>
<% } %>
</select>
If you wanted to use the HtmlHelper you can write:
<%=Html.DropDownList("holidayCities", Model.HolidayCitiesSelectList) %>
Model.HolidayCitiesSelectList should be of type IEnumerable<SelectListItem>
This type of customization isn't avaiable for the built in helpers so you might end up creating your own Html.DropDownList helper method.
http://msdn.microsoft.com/en-us/library/system.web.mvc.selectlistitem(v=vs.98).aspx