I have a custom section, with a custom tree.
I'm having a bit of trouble understanding how you set the correct behavior when:
You click a node in your tree to edit it.
You click a menu item on a node like "Create"
In my solution I'm using the same view to edit and create a record.
In my tree this is how a node is generated.
var routeToView = "rewards/rewardsTree/editcampaign/campaign-" + campaign.Id.ToString();
var campaignNode = CreateTreeNode("campaign-" + campaign.Id.ToString(), id.Split('-')[1], queryStrings, campaign.CampaignName, "icon-folder color-yellow", true, routeToView);
This is producing the route I want: (the name of my html file is editcampaign.html) and it is also passing "campaign-6"
/umbraco#/rewards/rewardsTree/editcampaign/campaign-6
When a user clicks the create 'menu Item' on the node - I want to send them to the same URL but just with a diffrent Id for example:
umbraco#/rewards/rewardsTree/editcampaign/brand-1
and I don't want it to pop up out of the side
This is what I have tried so far:
//This finds the view, but it comes up in a dialog also how do I pass the Id (brand-1)
MenuItem mi = new MenuItem("editcampaign", "Create Campaign");
menuItemCollection.Items.Add(mi);
//Also Tried this finds puts a whole another umbraco UI inside a dialog
mi.LaunchDialogView("#rewards/rewardsTree/editcampaign/brand-1", "TITLE GOES HERE");
Can anyone point me to the fullest documentation for Menu's trees and navigation around the back office in general?
I believe there is an option to set view path on the "Create" menu item, which makes it open normally? Also, wouldn't it make more sense to have your path like /view/path/here/id ? Then when you create a new item just send 0 as id. Umbrangular on Github is a project with great examples of custom sections and views.
EDIT: Here's an example
protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
{
var menu = new MenuItemCollection();
MenuItem createCategory = new MenuItem("createcategory", "Create Category");
createCategory.AdditionalData.Add("ParentCategoryId", id);
createCategory.NavigateToRoute("/path/to/view/category/0");
createCategory.Icon = "add";
menu.Items.Add(createCategory);
return menu;
}
Related
I'm trying to implement integration tests on our React frontend which uses Ant design. Whenever we create a table, we add an action column in which we have a Menu and Menu Items to perform certain actions.
However, I seem unable to find the correct button in the menu item when using react-testing-library. The menu Ant design uses is rc-menu and I believe it renders outside of the rendered component.
Reading the testing-library documentation, I've tried using baseElement and queryByRole to get the correct DOM element, but it doesn't find anything.
Here's an example of what I'm trying to do. It's all async since the table has to wait on certain data before it gets filled in, just an FYI.
Tried it on codesandbox
const row = await screen.findByRole('row', {
name: /test/i
})
const menu = await within(row).findByRole('menu')
fireEvent.mouseDown(menu)
expect(queryByRole('button', { name: /delete/i })).toBeDisabled()
the menu being opened with the delete action as menu item
I had a same issue testing antd + rc-menu component. Looks like the issue is related to delayed popup rendering. Here is an example how I solved it:
jest.useFakeTimers();
const { queryByTestId, getByText } = renderMyComponent();
const nav = await waitFor(() => getByText("My Menu item text"));
act(() => {
fireEvent.mouseEnter(nav);
jest.runAllTimers(); // ! <- this was a trick !
});
jest.useRealTimers();
expect(queryByTestId("submenu-item-test-id")).toBeTruthy();
We've created solution where user has a table with files, each entry has checkbox. He can select as many as he like and then click download button.
We are using such resource, it should allow dynamically download, depending on selected items
private StreamResource createResource(final IndexedContainer container) {
return new StreamResource(new StreamSource() {
#Override
public InputStream getStream() {
for (Object o : container.getItemIds()) {
CheckBox checkbox = (CheckBox) container.getItem(o).getItemProperty(C_CHECK_BOX).getValue();
if (checkbox.getValue()) {
selectedFiles.add(o);
}
}
// do some magic to get stream of selected files
}
}, "download.zip");
}
The problem is that only second and following click on button is giving expected restults.
It's turns out that FileDownoader is getting resource from server and then it is sending current status of component . It is the reason why first click is giving stale result.
Do you have any idea how to overcome this? Is it possible to force: first update component and then download the resource?
Many thanks
Pawel
CheckBox in Vaadin is non-immediate by default, which means that it won't send a request to server when the checkbox is checked (or unchecked) on the browser. Immediate components send queued non-immediate events also to server but it seems that FileDownloader doesn't cause an event that would send non-immediate checkbox values to server.
The only thing you need to do is to set your checkboxes to be immediate when you create those:
checkBox.setImmediate(true);
FileDownloader will not suit your needs. As you can read in the documentation:
Download should be started directly when the user clicks e.g. a Button without going through a server-side click listener to avoid triggering security warnings in some browsers.
That means you cannot dynamically generate download.zip file determined by checkboxes values because that requires a trip to server.
You have at least 2 options. Either create new FileDownloader and generate new Resource download.zip every time user make changes to the checkboxes. Or you can add simple ClickListener to you Button with this line of code:
getUI().getPage().open(resource, "_blank", false);
Related: Vaadin - How to open BrowserWindowOpener from a SINGLE BUTTON
There is also alternative solution to set checkBox.setImmediate(true); . It is possible to send current state of all components, just before click, instead of sending each checkBox change.
This solution is based on this answer: https://stackoverflow.com/a/30643199/1344546
You need to create file downloader button and hide it:
Button hiddenButton = new Button();
hiddenButton.setId(HIDDEN_ID);
hiddenButton.addStyleName("InvisibleButton");
StreamResource zipResource = createResource(container);
FileDownloader fd = new FileDownloader(zipResource);
fd.extend(hiddenButton);
Add css rule to your theme
.InvisibleButton {
display: none;
}
And then create another button, which 1st update state, and then click hidden button.
Button zipDownload = new Button("Download as ZIP file");
zipDownload.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(Button.ClickEvent event) {
Page.getCurrent().getJavaScript()
.execute(String.format("document.getElementById('%s').click();", HIDDEN_ID));
}
});
I have a simple use case: in a multi select Table
when the user selects 1 row, a context menu with two actions must be returned (DELETE and DOWNLOAD)
when the user selects more than one row, only the DELETE Action should be in the context menu
This is the code I use:
contactList.setMultiSelect(true);
final Action delete = new Action("Delete", FontAwesome.TIMES);
final Action download = new Action("Download", FontAwesome.DOWNLOAD);
contactList.addActionHandler(new Action.Handler() {
#Override
public Action[] getActions(Object target, Object sender) {
final Table table = (Table)sender;
// if Table is in multi select mode, getValues() returns Set of item id's
if (table.isMultiSelect() && ((Set)table.getValue()).size() > 1) {
return new Action[] {delete};
} else {
return new Action[] {delete, download};
}
}
...
I see that getActions() is called by the Table component every time a row selection is made. It returns the correct Action array. However, in the UI, only one context menu is used, independent of the actions returned.
This topic is not covered in The Book of Vaadin. There is an old question but the solutions is way too complicated and the solution suggested by Joonas is not working (in fact the case i describe here).
Its a well-known issue in Vaadin from version 6. Most people (including me) work-around this by using ContextMenu Addon
I have a page that contains multiple topics in accordion.
How can I post a link (on social media or other places) so when the user clicks it can view the topic I want without making him choose the desired one to view it?
The website is built in Joomla 2.5 using its native (mootools) accordions.
A temporary solution came to my mind is to make single pages containing only the content I want, but it won't help them view the other topics contained in the same page, unless the user clicks the same category.
MooAccordion has a display option. You could use like:
window.addEvent('domready', function () {
var index = window.location.search; // get query string
index = index.replace("?", ''); // remove the ?
index = index.length ? index : 0; // in case there in no query, display first
var myAccordion = new Fx.Accordion($('accordion'), '#accordion h2', '#accordion .content', {
display: index // the actual behavior you are looking for
});
});
Read more at Mootools docs
So you could try these links as demo:
http://jsfiddle.net/brM2v/show/?0
http://jsfiddle.net/brM2v/show/?1
http://jsfiddle.net/brM2v/show/?2
I am trying to create lists using FieldManagers (Horizontal and Vertical). In this list I have multiple clickable items like buttons, so I am not using ListField or ObjectListField.
I have successfully created the UI, but I am unable to attach a particular item id coming from the server. Also, on clicking a particular button in any list row, I want to get the item id and want to perform an action against that ID.
So, please let me know the idea how I can attach the id to a particular row while I am using FieldManager and then how I can generate event against that ID on clicking a button?
When you create a row, you are probably creating a (subclass of) Manager for each row.
At least, it seems like you are creating a ButtonField on each row.
What you can do is to attach a cookie to each row, or to each button, when you create it. A cookie is just an extra piece of information that's attached to an object. Then, when that row or button is clicked, you ask the row/button for the cookie, and use that to identify the row ID.
Every BlackBerry Field can have a cookie attached to it. Since the cookie is of type Object, you can make it anything you want.
For example, when creating the buttons for your rows:
for (int i = 0; i < numRows; i++) {
BitmapButtonField button = new BitmapButtonField(onImage, offImage, ButtonField.CONSUME_CLICK);
// use the row index as the cookie
button.setCookie(new Integer(i));
button.setChangeListener(this);
Manager row = new MyRowManager();
row.add(button);
add(row);
}
and then when the button is clicked:
void fieldChanged(Field field, int context) {
Object cookie = field.getCookie();
if (cookie instanceof Integer) {
Integer rowId = (Integer)cookie;
System.out.println("Row Id = " + rowId);
}
}
Note: I'm using the BlackBerry Advanced UI BitmapButtonField for this, but the cookie technique will work with any Field, or Manager class. See another example here.