SilverStripe: Adding the component to GridField grouping them in a div (toolbar) - silverstripe

I am working on a SilverStripe project. In my project, I am adding components to the GridField dynamically. Actually, I am trying to replace the existing components. Since there is no replace method, I have to remove the existing components and add the new components.
Following is my code
$grid = new GridField('ContentBlocks', 'Content Blocks', $this->owner->ContentBlocks(), $editor);
$grid->getConfig()
->removeComponentsByType(GridFieldAddExistingAutocompleter::class)
->addComponent(new CustomGridFieldAddExistingAutocompleter())
//configuring other components continue here
As you can see in my code, I am removing an existing component and adding a new custom component as a replacement for the one that was removed.
It added the custom component. But there is an issue with that. The issue is that on the front-end, the new component is not added at the exact position as the one that was removed.
See this screenshot:
As you can see in the screenshot, the search box (the custom component added) went out of the container or div that the add content block button resides in. If I did not do that replacement, they stay in the same row as in the screenshot below.
What I am thinking is that I am looking for a way to group them back together in one row. How can I do that? Is it possible?

Instead of removing and adding components of an existing GridFieldConfig, we can create our own GridFieldConfig and add the components that we want.
$contentBlocksFieldConfig = GridFieldConfig::create();
$contentBlocksFieldConfig->addComponent(new GridFieldButtonRow('before'));
$contentBlocksFieldConfig->addComponent(new GridFieldAddNewButton('buttons-before-left'));
$contentBlocksFieldConfig->addComponent(new CustomGridFieldAddExistingAutocompleter('buttons-before-right'));
$contentBlocksFieldConfig->addComponent(new GridFieldToolbarHeader());
$contentBlocksFieldConfig->addComponent(new GridFieldSortableHeader());
$contentBlocksFieldConfig->addComponent(new GridFieldFilterHeader());
$contentBlocksFieldConfig->addComponent(new GridFieldDataColumns());
$contentBlocksFieldConfig->addComponent(new GridFieldEditButton());
$contentBlocksFieldConfig->addComponent(new GridFieldDeleteAction(true));
$contentBlocksFieldConfig->addComponent(new GridField_ActionMenu());
$contentBlocksFieldConfig->addComponent(new GridFieldPageCount('toolbar-header-right'));
$contentBlocksFieldConfig->addComponent(new GridFieldPaginator(25));
$contentBlocksFieldConfig->addComponent(new GridFieldDetailForm());
$contentBlocksField = GridField::create(
'ContentBlocks',
'Content Blocks',
$this->ContentBlocks(),
$contentBlocksFieldConfig
);
The above config component set up is based on the GridFieldConfig_RelationEditor setup. We could use the components of GridFieldConfig_RecordEditor or any of the other configs instead.
Also, to align the Autocompleter to the right we pass 'buttons-before-right' as a parameter like so:
->addComponent(new CustomGridFieldAddExistingAutocompleter('buttons-before-right'))
This is assuming CustomGridFieldAddExistingAutocompleter has the same constructor as GridFieldAddExistingAutocompleter.

Related

How to add global barButtonItems to custom UINavigationBar?

I am currently trying to create a custom UINavigationBar Subclass.
What i want to achieve is that all custom navigationbars inside my app should have a couple of barbuttonitems in common. But it should still be possible to define left or .rightbarItems on the navigationItem in code.
What i tried so far is that subclassed the UINavigationBar and played around with all methods and delegate callbacks i could potentially use to change the navigationItem. There are methods like
setItems:animated:
setItems:
navigationBar:didPushitem etc.
.. which could be used to modify the navigationItem somehow.
But there is no callback which can be used to change the item initially.
What i basically want to know is how it is possible to change navigationItem initially before it is being pushed ?
Solved it by myself using
willShowViewController of the UINavigationControllerDelegateProtocol
to modify the navigationItem

Tapestry: custom component and title in Grid header

I need to change the title of a grid header, and add a custom component to it. I use a .properties file to set the title, and this template code to add the custom component:
<table class="table table-striped" t:type="grid" t:source="data" t:rowsPerPage="50" t:pagerPosition="bottom">
<p:specialHeader>
<t:tooltip tip="tipData"></t:tooltip>
</p:specialHeader>
</table>
When viewing the grid in a browser, the component appears but there is no title.
If I set a title in the template, like so, then it loses the sort functionality:
<p:specialHeader>Title
<t:tooltip tip="tipData"></t:tooltip>
</p:specialHeader>
How can I get the title, sort and custom component to appear?
As I said here you can't combine the default header block and your own custom header block, it's either one or the other.
I think you're best bet is a mixin. Take a look at Taha's blog post here where he creates a HelpText mixin which applies to a Label component. His mixin looks at the message catalog for a "propertyName-help" entry and adds a "title" attribute to the DOM. The blog post takes it one step further and uses a ComponentClassTransformWorker2 to atach the HelpText mixin to every label (even the ones inside the BeanEditor component).
You could do the same thing but you would create a mixin for either Grid or GridColumns (Grid delegates to GridColumns to draw the headers). If you'd like some examples of Grid mixins, take a look at my tapestry-stitch demo's here and here.
So, you won't be reusing the tooltip component, you will be copying the behaviour. This will most likely involve adding a "data-tooltip" attribute to the th DOM elements serverside. You can then fire some javascript on the client to find all elements with a "data-tooltip" attribute and do some UI magic.

Using several RenderComponentPresentations for XPM templates w/ Razor

As you probably already know, I'm working hard on some XPM templates with Razor. I've ran into another issue, this time concerning rendering components inside templates in order to make them siteEditable.
The following I'm not sure about. I've got a component which has a title field called "Title", and multivalue componentlink fields which consists of components with a title, description and image. Let's call this one "Linked USP" for now.
Currently this is being rendered by a Template called 'Page Banner', and it just iterates over fields with some If-loops to determine it's presentation, especially for the Title. In order for XPM to work, this template needs to render the component presentation of "Linked USP". So we've created a template called "[XPM] USP ITEM". - this Component template has the 'enable content editing TBB" added to it.
Now the issue arises when I want to make the Title Editable as well. Sounds straightforward, no? Not really - because when the parent template has got a "enable for content editing" TBB added, it will add <span> tags to all editable fields but the templates that gets invoked inside this template will also have <span> -tags, effectively bloating the html and making it impossible to edit the fields inside the RenderComponentPresentation because of duplicate <span>s.
Some code for your fun and to illustrate my issue:
<h1>#RenderComponentField("Title", 0)</h1>
#Foreach(var linkedUSP in Fields.USPS){
#RenderComponentPresentation("linkedUSP.ID", "tcm:10-1076-32")
}
This template has an enable Content edit TBB added.
now, for the RCP mentioned above, inside its [XPM] template:
<div class="title">#RenderComponentField("Title", 0)</div>
<p>#RenderComponentField("Description", 0)</p>
<tcdl:ComponentField name="img">
<img src="#img" alt="img.MetaData.alt">
</tcdl:ComponentField>
This one ALSO has the "Enable Content Edit" TBB added. On the front end this happens:
<div class="title"><span><span>Men</span></span></div>
Because the parent template also adds spans to the field.
So my question: how do i solve this? The Title field mentioned above has to be inside the parent template, but I can't create a special template for it becuase it is no component link. I can't get the TBB out of my RCP template, because it won't be editable that way. Interesting huh?
Can't I disable the spans inside template builder somehow?

Wrapper for custom Content Part - Orchard CMS

Using the Orchard admin I created a new Content Part called 'Spotlight Wrapper' with 3 HTML fields. I then created a Content Type Called 'Template 1' and assigned 'Spotlight Wrapper' to it. I then created a new 'Template 1' content item called 'Home Page'. I then created a file called Fileds_Contrib.Html-Spotlight Wrapper.cshtml to wrap each HTML field in the 'Spotlight Wrapper' with an and this is working. I have now added:
<Place Parts_SpotlightWrapper="Content:before;Wrapper=Parts_SpotlightWrapper" />
And created :
Views\Parts.SpotlightWrapper.cshtml
in an attempt to wrap the entire 'Spotlight Wrapper' Content Part in a but cannot seem to get it to work?
You declared a wrapper which I guess would lead to circular reference, as you try to wrap the Parts_SpotlightWrapper shape with itself. Wrappers are just separate pieces of Razor (cshtml) code that act as a parent for a given shape.
To achieve the behavior you want you should create a separate .cshtml file (eg. MyWrapper.cshtml) containing the necessary wrapper HTML code and attach it to your existing part like this:
<Place Parts_SpotlightWrapper="Content:before;Wrapper=MyWrapper" />
The wrapper code could look eg. like this:
<ul>
#Display(Model.Child)
</ul>
Btw - Try to look how it's done in Orchard.Widgets. There are two wrappers Widget.Wrapper and Widget.ControlWrapper that wrap the Widget shape. Declarations of those are not inside the Placement.info file (as you did), but hardcoded in Shapes.cs shape definition, though the final effect is perfectly the same. The technique with the Placement.info was just introduced later as a shortcut.
HTH

MvcContrib - How to get Area into MenuBuilder ActionLink

I am using MenuBuilder with code like this:
public static MenuItem MainMenu(UrlHelper url)
{
Menu.DefaultIconDirectory = url.Content("~/Public/Images/");
Menu.DefaultDisabledClass = "disabled";
Menu.DefaultSelectedClass = "current";
return Menu.Begin(
Menu.Items("",
Menu.Action<HomeController>(p => p.Index(), "Home")
),
Menu.Items("",
Menu.Secure<HomeController>(p => p.About(), "About")
),
Menu.Items("",
Menu.Action<RegulationController>(p => p.Index(null), "Compliance")
)/* This is in the Compliance area */
).SetListClass("menu");
}
But I am also using MvcContib Areas and in the code above the final menu item is in an 'Area' called 'Compliance'.
(There are two other areas in the Mvc application and the first in the list of registered areas is called 'Legislation')
What happens is the following:
When a page is rendered (I am using the standard WebFormsViewEngine) the Urls are all rendered using the 'Legislation' area!!?
E.g. http://localhost:1337/Legislation/Home or http://localhost:1337/Legislation/Home/About
and finally http://localhost:1337/Legislation/Regulation
The first two links should not pick up the 'Legislation' area. The last menu item should be in the 'Compliance' area.
How do I prevent the erroneous Area (Legislation) being rendered on the first two links?
How do I get the MenuBuilder markup in the Site.Master to accept an 'area' attribute or get it picked up automatically from the Controller for each link?
It seems that MvcContrib MenuBuilder does not play well with Areas. In the end I took the Areas out and the problem went away.
However, I recognise there may have been some other issue in the Mvc application which may indeed have been related to the older (beta?) version of Mvc dll that MvcContrib was referencing.
So for anyone that comes across this it may indeed be a none issue.

Resources