Silverstripe 3.0 customize tools panel - content-management-system

I want to show some customized content in the left panel which usually contains the treeview.
As the stuff in this panel will be an editable Gridfield wich should be related to the EditForm, I tried to built a new EditFormTools panel in this way:
I copied the CMSMain_Content.ss in mysite/templates/Includes and changed $Tools into $EditFormTools
I created the file CMSMain_EditFormTools.ss in the same directory with this code:
<div class="cms-content-tools west cms-panel" data-expandOnClick="true" data-layout-type="border" id="cms-content-tools-CMSMain">
<div class="cms-panel-content west">
<% include Test %>
</div>
</div>
I created a Test.php with:
class Test extends CMSMain{
public $var = 'test';
public function testfunction(){
$variable = 'hakuna matata';
return $variable;
}
}
Then I created a Test.ss with this code:
some Text
$var
$testfunction
$variable
The Panel appears in my CMS now but it only contains "some Text". So the include of Test.ss works perfectly fine but passing variables from Test.php to Test.ss doesn't.
Can anybody help?
Greetings

It may not directly answer your question but may give you direction.
You need to extend a controller class.
Then you can use a called functions to tell controller which template file it should use using renderWith().
for example,
public function index(){
return $this->renderWith("Test");
}
Then your function references in Test.ss will call functions in Test.php given it is the controller.
If Test class is not the controller rendering the template, the template doesnt know where your variable returning function is.
By the way, you can pass variables from layout to include template.

Related

Adding Scripts to Nop Commerce plugin

I am trying to add bootstrap to a Payment Plugin that I am developing and I do not know why it's not including the files in OnePageChekout page that includes the PaymentInfo.cshtml partial view...
Code:
#model Nop.Plugin.Payments.PluginName.Domain.PluginModel
#{
Layout = "";
Html.AddScriptParts("~/Plugins/Payments.PluginName/Scripts/bootstrap.min.js");
Html.AddCssFileParts("~/Plugins/Payments.PluginName/Content/bootstrap.min.css");
}
#using Nop.Web.Framework.UI
Tried this as well:
#model Nop.Plugin.Payments.PluginName.Domain.PluginModel
#{
Layout = "";
Html.AddScriptParts(ResourceLocation.Foot,"~/Plugins/Payments.PluginName/Scripts/bootstrap.min.js", true);
Html.AddCssFileParts(ResourceLocation.Head, "~/Plugins/Payments.PluginName/Content/bootstrap.min.css");
}
#using Nop.Web.Framework.UI
Tried to use Html.AppendCssFileParts and Html.AppendScriptFileParts and it did not worked.
When debugging...the code calls this functions and it's adding the file references to the _scriptsParts and _cssParts variables.
But at that moment it adds my scripts those variables do not have any more scripts which I think it's odd.
Also it never calls the GenerateCssFiles function which I think is the function that adds the scripts to the bundle because this is only called after the page (OnePageCheckout.cshtml) is loaded and never when a partial view is loaded in the main view.
Am I right in this assumptions ? How can I add scripts dynamically to the PaymentInfo.cshtml page ?

Given a Path get a reference to the Resource in Sightly

The component dialog has a pathfield widget where the authors can set a page path. In the Sightly component, I would like to look up that page resource and get (and display) properties from it.
The dialog...
<linkedPathLocation jcr:primaryType="cq:Widget"
fieldLabel="Linked Path"
name="./linkedPathLocation"
xtype="pathfield"
fieldDescription="Select a page. URL, Title, Description and Image are properties of the selected page"/>
The component code I would like to work (it's not).
<div class="row" data-sly-resource.page = "${properties.linkedPathLocation}">
<h1 >${page.title}</h1>
<p>${page.description}</p>
</div>
My question: Is there a way in Sightly to resolve and use some resource from a given path? If not, I could create a USE-API class and to do the following...
Page page = resourceResolver.resolve("/path/to/resource").adaptTo(Page.class);
I feel there should be a better answer which allows resources to be resolved directly from the Sightly, but the following USE-API solution works if not...
Java Use Class
public class PageHelper extends WCMUsePojo {
String pagePath = "";
#Override
public void activate() {
pagePath = get("path", String.class);
}
public Page getPage() {
return this.getPageManager().getPage(pagePath);
}
}
The component Sightly...
<div class="row" data-sly-use.linkedPage = "${'com.package.PageHelper' # path = properties.linkedPathLocation}">
<h1 >${linkedPage.page.title}</h1>
<p>${linkedPage.page.description}</p>
</div>
What you are trying to do, in essence, is render a Resource within the context of the rendering of another Resource. data-sly-resource seems the appropriate attribute to use, but instead of attempting to nest additional elements into the element containing the data-sly-resource you should define another Sightly .html file which dictates how the nested resource is to be rendered.
Let us say that your Resource is of type application/components/content/type. Within type.html you might have the following statement
<sly data-sly-resource="${properties.linkedPathLocation} # resourceType='application/components/content/type/subtype' />
You would then be able to define /apps/application/components/content/type/subtype/subtype.html containing the rendering to produce which would be invoked in the context of the Resource identified by your path.
The main purpose of Sightly templates is separation of responsibility (frontend & backend) so that we can have simple, clean and beautiful html markup which is designer friendly and easily readable.
For your case, writing a Class (Java/Javascript) to process dialog information, and supply it back to Sightly template is correct way. Read here for more details.

Where does the value of $Form come from, when using a standard SilverStripe template?

The Page Layout template for the "simple" theme (the default) contains:
<% include SideBar %>
<div class="content-container unit size3of4 lastUnit">
<article>
<h1>$Title</h1>
<div class="content">$Content</div>
</article>
$Form
$CommentsForm
</div>
Where does the value of $Form come from? ie to make use of it, what do I need to do?
Is it intended that I define a function Form() within the page controller that returns the form?
Yeah, it's a bit of an oddity. $Form is used by the Security controller, which is invoked in login situations (/Security/login, /Security/lostpassword, etc..) and because those templates can be themed, it assumes that you have a $Form variable somewhere in your template that indicates where the form should render.
You only need it in your Page.ss template, as the Security controller just renders a generic Page.
Anything in Silverstripe that extends ViewableData basically doubles as a ViewModel. This includes DataObject and Controller. So things that are publicly accessible on these objects are exposed to the View layer and callable as template variables (be they properties or methods).
Where does the value of $Form come from? ie to make use of it, what do I need to do?
So basically yes, your assumption is correct. If you define public function Form() (which returns a Form instance) in the page controller class you want the form to show on, it will render a form on the template (for all pages of that type).
Is it intended that I define a function Form() within the page controller that returns the form?
What UncleCheese intends to say in his answer is that the variable name $Form is arbitrary. Your method could for instance be named ContactForm(), in which case you'd need to give the template $ContactForm to show the form (be sure that the second parameter to Form constructor reflects this too - http://docs.silverstripe.org/en/3.1/developer_guides/forms/introduction/ using - __FUNCTION__ is a great way to avoid this gotcha).
Form() however does not appear as a function by default in page.php, nor in ContentController, etc. The Security controller however uses Page.ss to render (when you have the CMS module installed) - thus meaning if you do not have $Form in Page.ss somewhere, you will never be able to log in. So it's important to keep this unless you also define a Security.ss to make the login/lostpassword/etc. pages different to the normal Page.ss layout (in which case that template needs $Form).

Zend Form Element with Javascript - Decorator, View Helper or View Script?

I want to add some javacsript to a Zend_Form_Element_Text .
At first I thought a decorator would be the best way to do it, but since it is just a script (the markup doesn't change) then maybe a view helper is better? or a view script?
It seems like they are all for the same purpose (regarding a form element).
The javascript I want to add is not an event (e.g. change, click, etc.). I can add it easily with headScript() but I want to make it re-usable , that's why I thought about a decorator/view helper. I'm just not clear about the difference between them.
What is the best practice in this case? advantages?
UPDATE: Seems like the best practice is to use view helpers from view scripts , so decorators would be a better fit?
Thanks.
You could create your own decorator by extending Zend_From_Decorator_Abstract and generate your snippet in it's render() method :
class My_Decorator_FieldInitializer extends Zend_Form_Decorator_Abstract {
public function render($content){
$separator = $this->getSeparator();
$element = $this->getElement();
$output = '<script>'.
//you write your js snippet here, using
//the data you have in $element if you need
.'</script>';
return $content . $separator . $output;
}
}
If you need more details, ask for it in a comment, i'll edit this answer. And I didn't test this code.
Use setAttrib function.
eg:-
$element = new Zend_Form_Element_Text('test');
$element->setAttrib('onclick', 'alert("Test")');
I'm not actually seeing where this needs to be a decorator or a view-helper or a view-script.
If I wanted to attach some client-side behavior to a form element, I'd probably set an attribute with $elt->setAttrib('class', 'someClass') or $elt->setAttrib('id', 'someId'), some hook onto which my script can attach. Then I'd add listeners/handlers to those targeted elements.
For example, for a click handler using jQuery , it would be something like:
(function($){
$(document).ready(function(){
$('.someClass').click(function(e){
// handle the event here
});
});
})(jQuery);
The benefit is that it is unobtrusive, so the markup remains clean. Hopefully, the javascript is an enhancement- not a critical part of the functionality - so it degrades gracefully.
Perhaps you mean that this javascript segment itself needs to be reusable across different element identifiers - someClass, in this example. In this case, you could simply write a view-helper that accepts the CSS class name as the parameter.
"the markup doesn't change", Yap,
but I like to add some javascript function throw ZendForm Element:
$text_f = new Zend_Form_Element_Text("text_id");
$text_f->setAttrib('OnChange', 'someFunction($(this));');
The best way is if you are working with a team, where all of you should use same code standard. For me and my team this is the code above.

Zend Framework's Action helper doesn't use a ViewRenderer

I'm trying to execute an action from the view using the Action helper like but although the action is been executed the output isn't displayed.
Here's part of my .phtml file:
<div id="active-users">
<?php echo $this->action('active', 'Users') ?>
</div>
The action works like this:
class UsersController extends Zend_Controller_Action
{
function activeAction()
{
$model = new UsersModel();
$this->view->users = $model->getActiveUsers();
}
}
And there's another .phtml file that renders the list of users. The action works fine when called directly from /users/active but doesn't display anything when called from inside another .phtml file.
I've tracked the problem to the ViewRenderer not been available when called with action() helper... or at least not working as usual (automatically rendering the default .phtml file).
The content is displayed if I explicitly render the view inside the action but I need the ViewRender behaviour because I don't control the code of some of the actions I need to use.
Is there anyway to turn the ViewRenderer on while using the action() view helper? I'm open to replace the action() view helper if needed.
I forgot: I'm using PHP 5.2.8, Zend Framework 1.7.5, Apache 2.2 on Windows Vista.
Thanks
i think you should asign the active users from the controller or if you want you can use singleton on the models an use the directly in the views
$this->view = UsersModel::instance()->getActiveUsers();
Are you using _forward() o redirect on your action? Actions that result in a _forward() or redirect are considered invalid, and will return an empty string.
Update: I test it, and it works, try writing 'users' instead of 'Users' in the controllers param.
<div id="active-users">
<?php echo $this->action('active', 'users') ?>
</div>