How do you use chartkick with viewcomponent? - chartkick

When rendering chartkick charts in view_component and you have multiple charts in one page, the only one chart ends up getting rendered.
The issue is the same or similar to this one.
How do you render chartkick charts with view component?

In a parent component class like ApplicationComponent, define what you'll use as the chart's id:
def chartkick_chart_id
self.class.name.underscore.dasherize.gsub("/", "--")
end
Then, override chartkick_chart to set the id of the chart so that the default setting of chartkick does not kick in.
alias_method :orig_chartkick_chart, :chartkick_chart
def chartkick_chart(klass, data_source, **options)
opts = options.merge(id: chartkick_chart_id)
orig_chartkick_chart klass, data_source, **opts
end
This will work as long as you render one type of the same chart page page. If you render two charts in the same page (I don't see why you would), add some randomizing string to the ID.

Related

How do you add data bars to a chart via Java?

On startup, I'm trying to add a varying quantity of values to a barchart. I have an agent type Component. It has a few variables associated with it, one being hopperLevel. I create multiple Component agents based on an Excel sheet that assigns values to these variables. The number of Component agents created depends on the number of rows filled out on the Excel sheet. As the simulation runs, hopperLevel changes and I'd like to chart components(0).hopperLevel, components(1).hopperLevel, components(2).hopperLevel, etc. for all components.
I've tried the addDataItem method in the On startup field like this:
for ( Component comp : components )
{
chartHopperLevels.addDataItem(comp.hopperLevel, comp.componentName, blue);
}
but get the error:
"The method addDataItem(DataItem, String, Color) in the type BarChart is not applicable for the arguments (int, String, Color)"
I understand that an int isn't a DataItem, but I'm not sure what a DataItem is.
How do I use this method? Or is there a better way?
You cannot directly refer to an value in the addDataItem() function. This is because Java cannot monitor a value and do something if it changes.
Instead, AnyLogic has defined the DataItem which contains more or less only an update function which gets triggered and then pulls a new version of your value. The trigger can be automatically (setting Update data automatically in your chart) or manually (DataItem.update()). This update function is custom build for every value that you want to monitor.
You can build such a custom DataItem/update function (here: for variable myVariable) in the Additional class code in main:
public class MyDataItem extends DataItem{
#Override
public void update(){
super.setValue(myVariable);
}
}
You can the initialise your custom version of the DataItem like this:
DataItem di = new MyDataItem();
And finally you can add it (like you already did) to your barchart:
chart.addDataItem(di, "my value", red);
you need to read and understand the API on creating a DataItem first, see the AnyLogic help.
You can create a DataItem as below:
DataItem myItem = new DataItem();
myItem.setValue(12);
chart.addDataItem(myItem, "cool", Color.blue);
So you create a separate DataItem object first and then set its value to something you like. Then, you can add that to your bar chart (which is called "chart" in my example code above).
cheers

How to use selector

Let's say, I have a template A and sling:resourceType is /apps/myproject/components/basePage. In this component I've body.html and header.html and footer.html script included through slightly in body.html.
Now I am creating another template B, and sling:resourceType is /apps/myproject/components/compB and sling:resourceSuperType of compB is /apps/myproject/components/basePage.
In /apps/myproject/components/compB I have added content.html and selector.html
If I create a page (mytest.html) of type template B, then header and footer script is included correctly but when I hit this mytest.selector.html then header and footer script is not included. I want template B will have two different view based on selector.
Please let me know where I am missing.
I believe you are trying to include multiple scripts within same template to achieve different views. This is correct approach todo in AEM. But missing part is the moment you create the second script (selector.html in this case), it becomes another template and you need to code to include your entire page scripts into this script as well.
When you override scripts from /libs/wcm/foundation/components/page component, they ll work fine when your custom script names matches to parent component. For example your body.html will override /libs/wcm/foundation/components/page/body.html and page will render how it is coded. When you create selector.html it becomes independent script as there is no /libs/wcm/foundation/components/page/selector.html.
You need to define all behavior (to include header, footer script etc) explicitly against your custom script. In this case you need include header/footer scripts explicitly into your selector.html
Using a selector means that you're using some special implementation of your component. For instance, your component may have several charts and you want to encapsulate those in your selectors and use it through AJAX from browser, and reuse those selectors in your main component as well.
Currently, you're trying to achieve is to use your header and footer to another component which breaks the encapsulation rule. Rather do this, take out your header.html and footer.html and make those individual components and you it in your basePage as well as your child pages.
See the snippet below:
<div data-sly-resource="${'header' # resourceType='/apps/myproject/components/header'}">
<p>Your body and anything you want to put here</p>
<div data-sly-resource="${'footer' # resourceType='/apps/myproject/components/footer'}">
This way, you can reuse your headers whereever you want even in your selectors.

ZK Charts, clearing the chart

I am using ZK charts in my project. I am having line type charts. And using addSeries on my chats. But when I want refresh charts as in when user if fetching new Data, I am not sure how to clear the graph. Please help.
For example, if you are using series to add points on the chart (in my example I am using Float values) you can empty data displayed by setting an empty list to the series, like this:
chart.getSeries().setData(new ArrayList<Float>());
this one worked for me,
just write this line before populating your chart
chart.getSeries().setData(0);
To do that just call the method
chart.invalidate();

In CQ How to disable any field in child page properties dialog?

I have added a new selection type field "Theme" in page properties>Basic.
Now if I add a new page using the same template in WCM, there also I
am getting the option "Theme", which is quite obvious.
Is there any way by which I can hide the field in child page?
P.S this is happening because I am using the same template for the child page.
You can't use the same template and have the page property dialogs be different.
What you can do is overload the dialog
create a new template and corresponding resourceType component that
inherit from your current.
copy the dialog, or tab that you want to be different from the lowest parent of the component. Make sure the dialog is the only node under the component.
Make the changes you want to the dialog.
You would then have to include code in the page jsp to get the parent page property something like:
// if the parent page is always a certain level below the root you can use
// currentPage.getAbsoluteParent(3); to get the third page down from the top
// of the current path tree.
Page parentPage = currentPage.getParent();
ValueMap parentPageProperties;
if (parentPage != null) {
parentPageProperties = parentPage.getProperties();
}
// This tries to get the property 'theme' from the current page. If that fails
// then it tries to get the property from the parent page. If that fails it
// defaults to blank.
theme = properties.get("theme", parentPageProperties.get("theme", ""));
A quick solution would also be to create a second set of template / page component. Let's assume you've got template A, that uses page component B as resource type:
Create template X and play with allowedParents allowedChildren and allowedPaths properties so that the two are exclusive (actual solution depends on your content architecture)
Give X same title as A
Create page component Y that extends B, and defines it's own dialog
Make Y's dialog re-use any tabs from B using xtype=cqinclude (see foundation page's dialog for reference)

Styling Data Grids in GWT - Multiple Grids in one project

I am attempting to have multiple data grids in a single project. They have some different behavior and therefore different styling. The first grid is a fully custom grid, building the rows with an AbstractCellTableBuilder with a fully custom CSS file (using the DataGrid.Resources override).
The issue I am having is that my second grid's custom CSS is being applied to my first grid. I don't see any coding overlap. It just seems like the CSS classes are being anonymized the same, so they show up on the elements both grids.
Any thoughts?
Please let me know if there is anything I can provide to clarify the situation.
UPDATE:
ReportSelectorGrid.css has every class required by the DataGrid.Style defined. All of them are empty.
private SelectorDataGridResources gridResource = GWT.create(SelectorDataGridResources.class);
public interface SelectorDataGridResources extends DataGrid.Resources {
#Source({ "ReportSelectorGrid.css" })
DataGrid.Style dataGridStyle();
};
And then this is in my UiFactory method:
DataGrid<ReportSelectorItem> grid = new DataGrid<ReportSelectorItem>(-1, gridResource, KEY_PROVIDER);
You have to declare a DataGrid.Style sub-interface or they'll all share the same obfuscated class names. See also: https://code.google.com/p/google-web-toolkit/issues/detail?id=6144