Silverstripe: Dataobject in Siteconfig output in template - has-many

I have a problem similar described on the silverstripe problem: [http://www.silverstripe.org/dataobjectmanager-module-forum/show/19853][1]
I have a working DataObject, wich mainly provides a Title, Caption and Image.
This goes in an has_many, which should provide a slider in the template output.
The CMS part is all done, meaning I can add multiple 'slides' from a tab in the SiteConfig.
Only the output in the template won't seem te happen.
For the codes I use:
SingleSlide extends DataObject:
public function getCMSFields_forPopup()
{
return new FieldSet(
new ImageUploadField('SlideImg', 'Afbeelding van slide'),
new TextField('SlideTitle'),
new TextField('SlideCaption'),
new SimpleSiteTree('SlideLinkID')
);
}
In SiteConfigOverride
$fields->addFieldToTab('Root.SliderA', new ComplexTableField(
$this->owner, 'SliderA', 'SingleASlide',
array('SlideImg' => 'Afbeelding van slide', 'SlideTitle' => 'Titel van Slide', 'SlideCaption' => 'Tekst bij slide', 'SlideLink.Title' => 'Link naar pagina'
)));
All left to do is be able to get the Output from here in the template.
Any help would be great!
Regards,
Kay

You can add a function to the Page_Controller class in Page.php such as below
class Page_Controller extends ContentController {
...
function SingleSlideList() {
return DataObject::get('SingleSlide');
}
...
}
Then in your ss file, you can use something like the following:
<% control SingleSlideList %>
<div class="Image"><% control SlideImg %><% control CroppedImage(880,493) %><img src="$BaseHref$Filename.XML" height="$Height" width="$Width"><% end_control %><% end_control %></div>
<div class="Content">
<h2>$SlideTitle</h2>
<p>$SlideCaption</p>
<p>my link</p>
</div>
<% end_control %>
you will need to change the html to work with what you need.

Related

Silverstripe Sessions or URL Parameters

I'm trying to figure out how to pass a value from my .ss page to my controller for a custom search filter that I've built. The idea is you click on this image or a form button and then the page will set a session variable and refresh itself. Upon page load the page loads different information depending on what it reads in the session variable. I can accomplish the same thing with URL Parameters but there are no examples online that I could find that would show me how to do this.
Basically I have this as my php:
class ArticleHolder_Controller extends Page_Controller {
public function ValidateType(){
if(isset($_SESSION['mySearchTag']) && !empty($_SESSION['mySearchTag'])) {
$tag = $_SESSION['mySearchTag'];
}
else{
$tag='News';
}
$filter = $this::get()->filter('Filters:PartialMatch', $tag)->First();
if ($filter == NULL){
return NULL;
}
else{
$_SESSION['mySearchTag']=$tag;
return $this->PaginatedPages();
}
}
public function PaginatedPages(){
$paginatedItems = new PaginatedList($this->filterArticles($_SESSION['mySearchTag']), $this->request);
$paginatedItems->setPageLength(3);
return $paginatedItems;
}
public function filterArticles($tag){
return ArticlePage::get()->filter('category:PartialMatch', $tag)->sort('Date DESC');
}
}
my .ss looks like this:
<% if ValidateType() %>
<ul>
<% loop $PaginatedPages %>
<li>
<div class="article">
<h2>$Title</h2>
<h3>$Date</h3>
<img class="indent" src="$Photo.link" alt="image"/>
<p class="indent">$Teaser</p>
</div>
</li>
<% end_loop %>
</ul>
<% include Pagination %>
<% else %>
<p>SORRY NO RESULTS WERE FOUND</p>
<% end_if %>
This code works as is. What I cannot figure out how to now add a clickable button on .ss page that will reload the page and set a session variable value.
If I can achieve this with url parameters then that can work too, I just need to know how to set them in the .ss page and how to retrieve them in the php.
Create a SetFilter function that will take the URL parameter ID and set it to your session variable:
public function SetFilter() {
if($this->request->param('ID')) {
$_SESSION['mySearchTag'] = $this->request->param('ID');
}
return array();
}
Make sure your SetFilter function is added to the $allowed_actions of your controller:
static $allowed_actions = array (
'SetFilter'
);
This function is called by your page link followed by /SetFilter/[your-filter].
In your template you would create a link to create this filter like so:
Filter articles by example

Custom Client Template Telerik Grid

I'm kind of new using Telerik Grid, basically what I'm trying to accomplish here is the following scenario, I have a form that have some fields and via ajax calls another action on my controller to generate the model to a partial view that have the following grid, my problem is that I need to create some actions depending on some business logic, I know I can do that using a column template, the thing is that since im using ajax binding it "loose" my template, looking around on internet I found that you can do that using a js function go generate the links, my question is isn't that kind of messy? im duplicating the same business logic on the server and on the client, there's must be a better way to accomplish this?
Html.Telerik().Grid(Model)
.Name("Grid")
.DataBinding(binding => binding.Ajax().OperationMode(GridOperationMode.Client))
.Columns(column =>
{
column.Bound(c => c.Id).Title("Id").Width(30);
column.Bound(c => c.Status);
column.Bound(c => c.DateReg);
column.Template(
#<text>
<div class="ActionsProvGrid">
<a href="#Url.Action("SomeAction", "Controller", new {id = item.id})">
<img src="../../Content/icons/ViewMore.png" alt="ViewMore" />
</a>
#if (#item.Status.Equals("ACT"))
{
<a href="#Url.Action("SomeOtherAction", "Controller", new {idOportunidad = item.id})">
<img src="../../Content/icons/invoice.png" alt="invoice"/>
</a>
}
</div>
</text>
).ClientTemplate("<#= GenearteIcons(data) #>");
})
.Sortable()
As a solution you can define property on your model that encapsulates the result of your business logic:
public bool DoesStatusEqualToAct {
get
{
return (code that determines if it's true);
}
}
And in JavaScript function that generates a link html you can access this property:
function GenerateIcons(data){
var html = '';
if(data.DoesStatusEqualToAct){
html = 'version 1';
}
else{
html = 'version 2';
}
return html;
}

Rendering Partial Views in a Loop in MVC3

I have a pretty simple scenario, Model for my view is a List.
Loop through List like
#foreach(CustomObject obj in Model)
{
Html.Partial("_TrackingCustomObject",obj)
}
So i was expecting to have number of partial views according to my list.
Partial View has been developed accordingly.
There is no error on page. It just does not show any data that is supposed to display by partial views.
What is the reason of not showing any data?
You are missing an #:
#foreach(CustomObject obj in Model)
{
#Html.Partial("_TrackingCustomObject", obj)
}
But why writing foreach loops when you can use editor/display templates? Like this:
#model IEnumerable<CustomObject>
#Html.EditorForModel()
and then simply define the corresponding editor template (~/Views/Shared/EditorTemplates/CustomObject.cshtml) that will automatically be rendered for each element of your model:
#model CustomObject
<div>
#Html.EditorFor(x => x.Foo)
</div>
Simple and conventional :-)
You're missing the Razor symbol #:
#foreach(CustomObject obj in Model)
{
#Html.Partial("_TrackingCustomObject",obj)
}
Also make sure your partial view is using the object type CustomObject as the Model.
#model MyProject.Models.CustomObject
<h1>Yeah we're in a partial! #Model.SomeProperty </h1>
To try and drill down to where the error is, try placing some static text inside the PartialView.
<p>Some text</p>
If your collection has 10 items, then you should see 10 of these paragraphs. Next once this works, focus on displaying some property in each item.
#model MyProject.Models.CustomObject
<p>Some text</p>
<p>#Model.SomeProperty</p>
When you are creating html form using #Html.BeginForm() you have to wrap the remaining stuf inside a <div> or other container else the html elements won't get rendered.
Ex.
this won't work
#using(Html.BeginForm())
{
Html.EditorFor(m => m.Name)
}
this will work
#using(Html.BeginForm())
{
<div>
#Html.EditorFor(m => m.Name)
</div>
}
Bit late in the day, but this worked for me in MVC 4:
#foreach (var p in #Model.RelatedCards)
{
Html.RenderPartial("_ThumbPartial", p);
}
Try this:
#Html.RenderPartial("_TrackingCustomObject",obj)
This is too old but someone can use it.
#foreach(CustomObject obj in Model)
{
<text>
Html.Partial("_TrackingCustomObject",obj)
</text>
}

SilverStripe get half of image width/height

how can I get calculate with image height and width? I am trying to center an image like described in the first answer:
How to make an image center (vertically & horizontally) inside a bigger div
That's what I have tried so far:
<% control ProfileImage %>
<% if getOrientation = 1 %>
<img src="$URL" style="margin-left: -{$Width/2)}px" class="portrait"/>
<% else_if getOrientation = 2 %>
<img src="$URL" class="landscape"/>
<% end_if %>
<% end_control %>
The output of the decisive line is:
<img src="/assets/Uploads/picture.jpg" style="margin-left: -{154/2)}px" class="portrait"/>
Then I tried to write an own function:
class Profile extends Page{
//...
function GetHalfWidth(){
return ($this->ProfileImage->Width)/2;
}
//...
}
But I get the following error when I try to view the page in the frontend:
[Notice] Trying to get property of non-object
To get at the width of your image in the model you can change your function to read:
function GetHalfWidth() {
$width = $this->obj('ProfileImage')->Width;
return $width / 2;
}
However, if you are trying to reference that method form within the control loop of ProfileImage you'll need to 'jump out' and use $Top.GetHalfWidth
I would think a better way to handle it would be to define it as a method of your ProfileImage, if ProfileImage was subclassed from Image...
In Profile.php
<?php
class Profile extends Page {
...
public static $has_one = array(
'ProfileImage' => 'Profile_Image'
);
...
}
class Profile_Controller extends Page_Controller {
...
}
class Profile_Image extends Image {
function GetHalfWidth() {
$width = $this->Width;
return $width / 2;
}
}

Razor syntax to declare action that renders html

I'm trying to create an action that renders some html in the razor view engine. This was pretty easy in the webforms engine but I'm having some issues with razor. Here is the simplest form of what I'm trying to accomplish using the webforms engine:
<% var myAction = new Action<HtmlHelper<int>>((helper) => { %>
<div>
<%= helper.ViewData.Model %>
</div>
<%}); %>
The closest I've come in the razor view engine is:
#{var myAction = new Action<HtmlHelper<int>>((help) =>
{
#<div>
#help.ViewData.Model
</div>;
});
}
This gives a "CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement" error.
Any help would be appreciated. Thanks.
#{
Func<dynamic, object> myAction =
#<div>
#item.ProductName
</div>;
}
#myAction(Model)
You may also checkout the following blog post.
UPDATE:
You may also do this:
#{
Func<HtmlHelper<int>, object> myAction = #<div>#item.ViewData.Model</div>;
}
or:
#{
Func<dynamic, object> myAction = #<div>#item.ViewData.Model</div>;
}
and to invoke:
#myAction(someInstanceOfTheRequiredHelper)

Resources