How to access ZK components from JavaScript - javascript

I want to set value of a zk datebox from javascript. Actually I can set the value but when I want to access its value, it is throwing a null pointer exception. More generally, some abilities of the zk components can be manupulated but others not. For example I can fire a button onclick event but I can not set an attribute of that button by javascript.
For example these two work :
zk.Widget.$('$startDateProxy').setValue(start); zk.Widget.$('$addEventBtn').fire('onClick');
But these two not:
zk.Widget.$('$startDateProxy').setAttribute("startDate",start) -> cutting the operation
alert(startDateProxy.getValue().toString()) -> null pointer
Thanks
PS: I am trying to use FULLCALENDAR (arshaw.com/fullcalendar)

Thank you for your answer. startDateProxy component is Datebox, not Calendar. Sorry for missing information. I solved the problem by using AuService. I defined a hidden button. Fired its onClick with the parameters. Sample usage:
Client Side:
zk.Widget.$('$eventBtn').fire('onClick',{start : start ,end : end});
Server Side:
public void service(AuRequest request, boolean everError) {
if (Events.ON_CLICK.equals(request.getCommand())) {
Map data = request.getData(); // can be read start,end parameters from here
//dosomething here
}

Try it instead
alert(this.$f('addEventBtn').getLabel());
The Class Calendar does not have a setAttribute method (see the docs).

Related

How can I change Vaadin Components in Java through Javascript

I implemented Shepherd in my Vaadin Project, so i can guide users in tours through my web application.
But, i need to get access from the javascript on the Accordion Components in Vaadin, to open or close specific tabs. For this, i need to have access on the open() and close() method for the Accordion Components. So how can i access them through Javascript?
Already seen the Tutorial on the Website of them:
Vaadin calling java from javascript,
but sadly nothing over there, what could help me.
I already tried to use something like this:
UI.getCurrent().getPage().executeJs("window.startTour($0, $1)", this, Accordion1.getElement());
But when i try to bind it in javascript through:
window.startTour = (element, accordion) => { ... }
and in this window:
beforeShowPromise: function () {
return new Promise(function(resolve) {
element.$server.openAccordion(accordion.$server, 1);
resolve();
});
},
with the following method in java:
#SuppressWarnings("unused")
#ClientCallable
public void openAccordion(Object object, int index) {
Accordion accordion = (Accordion) object.get(this);
accordion.open(index);
}
i only get the following error message:
Class '...' has the method 'openAccordion' whose parameter 0 refers to unsupported type 'java.lang.Object'
No matter what i use as first parameter, everythin that extends Object doesnt work and i dont know why.
I found a recent post with the same question, but it was not helpful for me:
Unable to send a new bean instance to the server
Im using Intellij and in my Project: Java, Spring, Vaadin and Shepherd
Already tried to use different parameters, but only the int parameter is working, Object doesnt work.
The Problem is, i cant change the opened Tab of the Accordion from the Javascript over the Java, because of this error, so i have to implement for each Accordion 2 methods to open and close it.
Maybe somebody can help me with it or knows some tricks to master this.
Thanks
When using #ClientCallable you can pass only json or primitive types from JavaScript call to server. There is a real systems boundary here. Object is not supported and furthermore, you can cast that parameter to Java object.

Vaadin 14.4.0 manipulate the back/forward history buttons (onHashChange perhaps)

I have a single page, single class Vaadin project. In this project, I might change the layout to make it seem as if a new page has been entered. But since no new link/page is approached, I cannot figure out how to allow users to "return" to the previous element.
For a bit, I thought I could change the url, and then catch whether people used the forward or backward buttons. I have found hashChange events, but I cannot make sense of it or make it work. Vaadin has a HistoryChangeEventHandler, but it does not listen for hashChanges, and as such my solution would not work.
I am coming up short with regards to solving this. I found this thread from 2019, which seems to be a solution to my issue, but I cannot make the code work. I suppose I am trying to pass a wrong element to the javaScript execution.
So, I have a simple mainview that extends a div. In this div, I have the following code:
History history = UI.getCurrent().getPage().getHistory();
TextField textField = new TextField();
add(textField);
Button button = new Button();
button.setText("New link");
button.addClickListener(e-> history.pushState(null, "#"+textField.getValue()));
add(button);
Button button1 = new Button();
button1.setText("Go back");
button1.addClickListener(e-> history.back());
add(button1);
getElement().executeJs(
"const serverCallback = element.$server.onHashChange; this.window.addEventListener('hashchange', function () {serverCallback(location.hash);}, false);"
);
#ClientCallable
public void onHashChange(String hash) {
System.out.print("test "+hash);
}
I expected that the onHashChange method would be called. But I am getting a javascript error saying: (ReferenceError) : element is not defined.
Working solution:
getElement().executeJs("const serverCallback = $0.$server.onHashChange;" +
"window.addEventListener('hashchange', function () {serverCallback(location.hash);}, false);", getElement());
My getElement() is the extended div, I guess. And here is my onHashChange method.
#ClientCallable
public void onHashChange(String location) {
System.out.println("Current location is: " + location);
}
Also, if you ever wanted to just call a java method from vaadin. You can do the following:
getElement().executeJs("$0.$server.onHashChange(\"It works\");", getElement());
Good luck! And thank you Erik for taking the time to help out.
Looking at the JavaDoc for executeJs, it says:
* Asynchronously runs the given JavaScript expression in the browser in the
* context of this element.
* ...
* This element will be available to the expression as <code>this</code>.
So try replacing element.$server with this.$server.

How to disable javascript error debugging in IE WebBrowser Control

Application is using IE WebBrwoser Control. However sometimes javascript error dialogs comes up,to solve this put_silent property was used on WebBrowser element,but that disables all the dialogs.So is there a way to disable Javascript error debugging in WebBrowser control?
On your control do right click and click on Inspect Element. If you did not disable the IE menu, it should open the Developer window on right or bottom side. Select there the tab "Debug", click on the hexagon and check "Don't stop on exception" or "Stop on unhandled exceptions". I believe this is a global setting for the browser, so you maybe can do it just from IE.
Update 1
First implement IDocHostUIHandler and wrap the external handler calls. It is declared in Mshtmhst.h so you probably have to include it. Don't forget about IUnknown members, also have to be wrapped. ATL wizards can be used to implement interfaces, but anyway you will have to understand exactly that you do:
class MyDocHostUIHandler: public IDocHostUIHandler
{
public:
IDocHostUIHandler* externalHandler;
HRESULT EnableModeless( BOOL fEnable)
{
return externalHandler->EnableModeless(fEnable);
}
HRESULT FilterDataObject(IDataObject* pDO, IDataObject** ppDORet)
{
return externalHandler->FilterDataObject(pDO, ppDORet)ș
}
.... Wrap all the functions from External Handler like above
};
Create an instance of your class:
MyDocHostUIHandler* myHandler = new MyDocHostUIHandler();
Then in your code call like it is specified in MSDN.
First you get the MSHTML object
CComPtr<IHTMLDocument2> m_spDocument;
hr = m_WebBrowser->get_Document(&m_spDocument);// Get the MSHTML object
Then you get the existing default handler
ComPtr<IOleObject> spOleObject;
hr = m_spDocument.As(&spOleObject);
ComPtr<IOleClientSite> spClientSite;//<--this will be the default handler
hr = spOleObject->GetClientSite(&spClientSite);
Save the existing handler to your class, so you will be able to wrap its functions
//see myHandler is the instance of interface you implemented in first step
myHandler->externalHandler = spClientSite;
Get the custom doc:
ComPtr<ICustomDoc> spCustomDoc;
hr = m_spDocument.As(&spCustomDoc);//m_spDocument it is the pointer to your MSHTML
Now replace the handler from HSMTML:
//myHandler is the instance of class you implemented above
spCustomDoc->SetUIHandler(myHandler);
After this step, the MSHTML should not notice anything, but you will be able to add breakpoints in your MyDocHostUIHandler class and see which function is called by your MSHTML and when.

Search a Sencha TreePicker

I am using TreePicker from ExtJS 6.0.2. I would like to know how can I perform a search or query on the Picker data similar to this example - Fiddle. It has this property which is an built-in feature from combo-box:
queryMode: 'local'
I have made the TextField editable and I want to know if there is any inbuilt way to perform a search or do I have to write code to do it manually. For the manual way I tried to capture the change event of the TextField by writing the code for it in the config property of the TreePicker but failed to get the event to be fired. What am I missing here, please guide.
it seems this component has a very simple implementation and doesn't support any search functionality.
You could start to implement your need studying the Ext.form.field.ComboBox source code in order to "copy" only the behaviours you want.
For example you will see there's a picker's method to override to handle the change event. A very very simple "search on change" extension can be added with the following override:
...
onFieldMutation: function(e) {
var me = this,
store = me.getStore(),
rawValue = me.inputEl.dom.value;
store.filter('text', rawValue);
},
...
Fiddle

Get primefaces widgetVar in javascript and update it

I have a primefaces component like this:
<p:panel styleClass="errorsPanelClass" id="errorsPanel" header="Messages" toggleable="true" effect="drop" toggleSpeed="0" closeSpeed="0" widgetVar="errorsPanelWidget">
and i'm trying to get the component in javascript context and update it.
I already tried with:
function getWidgetVarById(id) {
for (var propertyName in PrimeFaces.widgets) {
if (PrimeFaces.widgets[propertyName].id === id) {
return PrimeFaces.widgets[propertyName];
}
}
}
or
How to find a widgetVar?
or
Get widgetVar with JavaScript or check/uncheck all other PrimeFaces checkboxes
It will be great if I'll find a solution to take the widgetVar by class, but any other solutions are welcomed.
I also tried:
function getWidgetVarById() {
for ( var propertyName in PrimeFaces.widgets) {
alert(PrimeFaces.widgets[propertyName].id);
}
}
but I get an javascript error "'PrimeFaces.widgets.length' is null or not an object"
Any ideas?
There is not mapping between the id and a widgetVar for PrimeFaces 3.5. In 3.5 the widgets are added to the 'window' object and not stored somewhere else. This means that the widgetVar is already directly a variable u can use.
<p:panel id="errorsPanel" widgetVar="errorsPanelWidget">
3.5/4.0: (in 4.0 this still works but is deprecated in favour of the PF('..') way)
errorsPanelWidget.close()
5.0 and up:
PF('errorsPanelWidget').close() (unless you configure the legacy mode after which it will behave like 3.5/4.0)
Easiest is then to use a convention that you name your widgetVar like your id but with a postfix e.g. id_widget. You could (advise against it) leave the widgetVar out and then the widget is idententical to the id (this can cause classhes in cases, that is why PF dropped this convention).
And you could still check if in 3.5 the widgetVar value is in one way or another added to the outer html element of the widget. You could then retrieve it with some jquery. Personally, I used the 'convention' way in previous PF versions (appending 'Widget' to the value that is also in the id and putting that in the widgetVar attribute)
And if with 'updating' the widget, you mean updating the content of the widget, you can't. There is no refresh() kind of method that does this. What you could do is send the id(!) to the server and execute an update(..) there via the requestContext like this
RequestContext context = RequestContext.getCurrentInstance();
context.update("errorsPanel");
But it might be even better to just to this the moment you update the list serverside. So it might be that you've fallen into the XY trap.
But if it is really needed, here is an example that works, using the PrimeFaces extensions remoteCommand since that is the easiest way)
xhtml:
<pe:remoteCommand id="refreshWidgetCommand" name="refreshWidget" process="#this" actionListener="#{updateWidgetController.refresh}">
<pe:methodSignature parameters="java.lang.String"/>
<pe:methodParam name="id"/>
</pe:remoteCommand>
Bean:
#ManagedBean
#RequestScoped
public class UpdateWidgetController {
public void refresh(final String id) {
RequestContext context = RequestContext.getCurrentInstance();
context.update(id);
}
}
calling refreshWidget('errrosPanel'); will achieve what you want.
Don't wan't to use PFE (or can't use this due to version incompatibilities), you can achieve the same with PF remoteCommand But the specific example for 3.5 might differ a little

Categories

Resources