When file is uploaded, a Button is enabled:
// myUploadComponent extends Upload
myUploadComponent.addSucceededListener(event -> enabledMyButtonMEthod ()); // working well
I don't find out how to disable that Button when I remove the file (click on the cross next to it).
There should be something like 'addRemoveListener' ... ?
How can I detect this event ?
You can listen to the "file-remove" event in the upload component. Here is an example.
#Route("")
public class MainView extends VerticalLayout {
public MainView() {
MyUpload upload = new MyUpload();
upload.addFileRemoveListener(e -> Notification.show("Button disabled"));
add(upload);
}
class MyUpload extends Upload {
Registration addFileRemoveListener(ComponentEventListener<FileRemoveEvent> listener) {
return super.addListener(FileRemoveEvent.class, listener);
}
}
#DomEvent("file-remove")
public static class FileRemoveEvent extends ComponentEvent<Upload> {
public FileRemoveEvent(Upload source, boolean fromClient) {
super(source, fromClient);
}
}
}
I have added and event listener like so
upload
.getElement()
.addEventListener(
"file-remove",
event -> {
JsonObject eventData = event.getEventData();
String fileName = eventData.getString("event.detail.file.name");
// ...
}).addEventData("event.detail.file.name");
Found the solution here: https://github.com/vaadin/vaadin-upload/issues/347#issuecomment-516292999
I would try public Registration addChangeListener(Upload.ChangeListener listener) which should be triggered on the filename change event
I have extended Tulio's solution to get the removed file name as well in the FileRemoveEvent. Comes in very handy!
private class MyUpload extends Upload {
public MyUpload(MultiFileMemoryBuffer buffer) {super(buffer);}
Registration addFileRemoveListener(ComponentEventListener<FileRemoveEvent> listener) {
return super.addListener(FileRemoveEvent.class, listener);
}
}
#DomEvent("file-remove")
public static class FileRemoveEvent extends ComponentEvent<Upload> {
private String fileName;
public FileRemoveEvent(Upload source, boolean fromClient, #EventData("event.detail.file.name") JreJsonString fileNameJson) {
super(source, fromClient);
fileName = fileNameJson.getString();
}
public String getFileName() {
return fileName;
}
}
Related
I am building a download manager
Here I have shown a test code which tries to update fileNameColumn of a row of tableView but it is not being updated after I connect to url
To be specific, here fileName remains hello1 and it doesnt get updated to hello2. Yhy's that so?
Main.java :
public static TableView<DownloadEntry> downloadsTable;
public TableColumn<DownloadEntry, String> fileNameColumn;
public void initialize(URL location, ResourceBundle resources) {
downloadsTable = new TableView<DownloadEntry>();
fileNameColumn = new TableColumn<>("File Name");
fileNameColumn.setCellValueFactory(new PropertyValueFactory<>("fileName"));
executor = Executors.newFixedThreadPool(4);
}
public void addDownloadButtonClicked() {
try{
String urlText = urlTextBox.getText();
DownloadEntry task = new DownloadEntry(new URL(urlText));
downloadsTable.getItems().add(task);
executor.execute(task);
}
catch(Exception e) {
System.out.println("addDownloadButtonClicked: " + e);
}
}
DownloadEntry.java:
public class DownloadEntry extends Task<Void> {
public SimpleStringProperty fileName;
public URL url;
//Constructor
public DownloadEntry(URL ur) throws Exception{
fileName = new SimpleStringProperty("hello");
url = ur;
}
#Override
protected Void call() {
try {
HttpURLConnection connect=(HttpURLConnection)url.openConnection();
fileName.set("hello1");
connect.connect();
fileName.set("hello2");
}
catch(Exception E) {
this.updateMessage("Error");
E.printStackTrace();
}
return null;
}
public String getFileName() {
return fileName.get();
}
public void setFileName(String fileName) {
this.fileName = new SimpleStringProperty(fileName);
}
}
Please tell if you need more details..
Your model is incorrectly implemented. The setFileName method should be
public void setFileName(String fileName) {
this.fileName.set(fileName);
}
(The problem with your implementation is that the table is still observing the old property, not the new one you create.)
You will also need to provide a "property accessor" method:
public StringProperty fileNameProperty() {
return fileName ;
}
which will allow the table to properly bind to the property (so that it "knows" when its value changes).
I am implementing the Vaadin 7 Calendar and require to display more
event information than is contained in BasicEvent.
Below is some of the code I am using (events are not being displayed
on calendar):
please can you inform me what I need to add/change?
Thank you Steve...
public class CalEvent extends BasicEvent {
private java.lang.String customer = "";
public CalEvent() {
}
public java.lang.String getCustomer() {
return customer;
}
public void setCustomer(java.lang.String customer) {
this.customer = customer;
}
}
public class EvtProvider extends BasicEventProvider {
public void addEvent(CalEvent event) {
super.addEvent(event);
}
public void removeEvent(Event event) {
super.removeEvent(event);
}
}
public class Mgr {
Mgr() {
cal = new Calendar("My Calendar");
EvtProvider evtProvider = new EvtProvider();
cal.setEventProvider(evtProvider);
List<CalEvent> lst = getCalEvents();
for (CalEvent ev : lst) {
cal.addEvent(ev);
}
}
"more event information than is contained in BasicEvent."
For example?
BasicEvent can display a lot of content in event or Event description.
http://i.stack.imgur.com/uRlN4.png
I would like to create custom image component .So I followed step by step from Integrating with Server-side. For basic or first-step , I created for the test Server to Client RPC call as following steps.
MyComponentWidget.java
public class MyComponentWidget extends HTML {
public MyComponentWidget() {
getElement().setAttribute("class", "thumbnail");
}
public final void createCustomImage(final String url) {
getElement().setInnerHTML("<div class='delete-block'></div><img src=" + url + " />");
}
}
MyComponentState.java
public class MyComponentState extends AbstractComponentState {
private String url;
private String html;
public final String getUrl() {
return url;
}
public final void setUrl(final String url) {
this.url = url;
}
public final String getHtml() {
return html;
}
public final void setHtml(final String html) {
this.html = html;
}
}
MyComponentConnector.java
public class MyComponentConnector extends AbstractComponentConnector {
public MyComponentConnector() {
registerRpc(MyComponentClientRpc.class, new MyComponentClientRpc() {
#Override
public void getMessage() {
// never reach to this place
System.err.println("Reach Here !");
getState().setHtml(getWidget().getHTML());
}
});
}
#Override
public final MyComponentWidget getWidget() {
return (MyComponentWidget) super.getWidget();
}
#Override
public final MyComponentState getState() {
return (MyComponentState) super.getState();
}
#OnStateChange("url")
final void updateText() {
getWidget().createCustomImage(getState().getUrl());
}
}
MyComponentClientRpc.java
import com.vaadin.shared.communication.ClientRpc;
public interface MyComponentClientRpc extends ClientRpc {
void getMessage();
}
MyComponent.java
public class MyComponent extends AbstractComponent {
public MyComponent(final String url) {
getState().setUrl(url);
}
public final MyComponentState getState() {
return (MyComponentState) super.getState();
}
public final String getHTML() {
getRpcProxy(MyComponentClientRpc.class).getMessage();
return getState().getHtml();
}
}
and call as
MyComponent image = new MyComponent("myImageUrl");
System.out.println(image.getHTML());
My problem is why I always get null value at my console ? I can see the image at browser but System.out.println(image.getHTML()); produces null. What am I missing ?
To make a rpc call from client to server, you must extend the ServerRpc interface, for example:
package com.example.client.MyServerRpc
public interface MyServerRpc extends com.vaadin.shared.communication.ServerRpc {
void sendHTML(String html);
}
In your connector your register the rpc:
private MyServerRpc rpc = RpcProxy.create(MyServerRpc.class, this);
And then you can send a value by using the registered rpc in your connector:
rpc.sendHTML(html);
To receive the value on your component's or extension's server-side class, you must create an instance of the rpc interface:
private MyServerRpc rpc = new MyServerRpc() {
#Override
public void sendHTML(String html) {
// this method will be called!
}
};
and register that in the constructor:
registerRpc(rpc);
After these steps RPC from client to server should work.
I create a Widget with his Server Side Class and the Client Side (Connector Class, ServerRPC Class, State Class and Widget Class).
Connector :
#Connect(Custom.class)
public class CustomConnector extends ButtonConnector {
...
public void myFunc() {
// DO Something
}
}
Widget :
public class CustomWidget extends VButton {
...
private CustomConnector conn = new CustomConnector();
public CustomWidget () {
conn.myFunc();
}
...
}
Now from the Widget Class i want to explicitly call/access the Connector Object, which are not a Singleton, so that i can access a function too. How can i solve it?
In my opinion you should not access connector directly from GWT widget. It is against Vaadin 7 architecture where GWT widgets are objects independent from vaadin at all.
However if we are talking about dirty migration from Vaadin 6 to 7 solution could be:
ComponentConnector connector = ConnectorMap.get(client).getConnector(CustomWidget.this); // client is taken from updateFromUIDL method (Vaadin6)
Better solution will be to add "state" listener to the widget
public interface CustomWidgetStateListener {
public void stateChanged();
}
public class CustomWidget extends VButton {
...
CustomWidgetStateListener listener;
public void addStateListener(CustomWidgetStateListener listener) {
this.listener = listener;
}
public void notifyStateChanged() { // You can call notifyStateChanged() whenever you want to notify connector
listener.stateChanged();
}
...
}
public class CustomConnector extends ButtonConnector {
public CustomConnector() {
getWidget().addStateListener(new CustomWidgetStateListener() {
public void stateChanged() {
myFunc();
}
});
}
...
public void myFunc() {
// DO Something
}
}
Using db4o client/server, updates are not working for collection properties of an object. I'm using transparent persistence, but that's not helping. Then, I changed my Collection property to ActivatableCollection, but no luck.
This is the server setup:
private void StartDatabase()
{
IServerConfiguration serverConfiguration = Db4oClientServer.NewServerConfiguration();
serverConfiguration.Networking.MessageRecipient = this;
serverConfiguration.Common.Add(new TransparentActivationSupport());
serverConfiguration.Common.Add(new TransparentPersistenceSupport());
string db4oDatabasePath = AppDomain.CurrentDomain.BaseDirectory;
string db4oDatabaseFileName = ConfigurationManager.AppSettings["db4oDatabaseFileName"];
int databaseServerPort = Convert.ToInt32(ConfigurationManager.AppSettings["databaseServerPort"], CultureInfo.InvariantCulture);
_db4oServer = Db4oClientServer.OpenServer(serverConfiguration, db4oDatabasePath + db4oDatabaseFileName, databaseServerPort);
string databaseUser = ConfigurationManager.AppSettings["databaseUser"];
string databasePassword = ConfigurationManager.AppSettings["databasePassword"];
_db4oServer.GrantAccess(databaseUser, databasePassword);
}
This is the entity that I want to save:
public class Application : ActivatableEntity
And this is the property within the Application entity:
public ActivatableCollection<TaskBase> Tasks { get; private set; }
This is the client code to update each object within the collection:
Application application = (from Application app in db
where app.Name == "Foo"
select app).FirstOrDefault();
foreach (TaskBase task in application.Tasks)
{
task.Description += ".";
}
db.Store(application);
Curiously, db.Commit() didn't work either.
There are two work-arounds, but I'd rather do this the "right" way.
Work-around 1: Call db.Store(task) on each task as the change is made.
Work-around 2: Before calling db.Store(), do this:
db.Ext().Configure().UpdateDepth(5);
Can anyone tell me why the list isn't updating?
If it helps, here is the ActivatableCollection class:
public class ActivatableCollection<T> : Collection<T>, IActivatable
{
[Transient]
private IActivator _activator;
/// <summary>
/// Activates the specified purpose.
/// </summary>
/// <param name="purpose">The purpose.</param>
public void Activate(ActivationPurpose purpose)
{
if (this._activator != null)
{
this._activator.Activate(purpose);
}
}
/// <summary>
/// Binds the specified activator.
/// </summary>
/// <param name="activator">The activator.</param>
public void Bind(IActivator activator)
{
if (_activator == activator) { return; }
if (activator != null && null != _activator) { throw new System.InvalidOperationException(); }
_activator = activator;
}
}
Indeed, transparent persistence needs a call to it's activator before every field access. However the intentions is that you do this with the enhancer-tool instead of implementing manually.
Another note: When you're using CascadeOnUpdate(true) everywhere db4o will end up storing every reachable activated object. If the object-graph is huge, this can be a major performance bottle-neck.
I was able to get transparent activation and persistence to work. I decided not to go with the approach for the reasons mentioned in my comment above. I think the easiest way to handle cascading updates is to simply use a client config like this:
IClientConfiguration clientConfig = Db4oClientServer.NewClientConfiguration();
And then either a bunch of these (this isn't so bad because we can add an attribute to every domain entity, then reflectively do this on each one):
clientConfig.Common.ObjectClass(typeof(Application)).CascadeOnUpdate(true);
Or this:
clientConfig.Common.UpdateDepth = 10;
return Db4oClientServer.OpenClient(clientConfig, databaseServerName, databaseServerPort, databaseUser, databasePassword);
Now, here is the server config that allowed me to get transparent persistence working.
private void StartDatabase()
{
IServerConfiguration serverConfiguration = Db4oClientServer.NewServerConfiguration();
serverConfiguration.Networking.MessageRecipient = this;
serverConfiguration.Common.Add(new TransparentActivationSupport());
serverConfiguration.Common.Add(new TransparentPersistenceSupport());
string db4oDatabasePath = AppDomain.CurrentDomain.BaseDirectory;
string db4oDatabaseFileName = ConfigurationManager.AppSettings["db4oDatabaseFileName"];
int databaseServerPort = Convert.ToInt32(ConfigurationManager.AppSettings["databaseServerPort"], CultureInfo.InvariantCulture);
_db4oServer = Db4oClientServer.OpenServer(serverConfiguration, db4oDatabasePath + db4oDatabaseFileName, databaseServerPort);
string databaseUser = ConfigurationManager.AppSettings["databaseUser"];
string databasePassword = ConfigurationManager.AppSettings["databasePassword"];
_db4oServer.GrantAccess(databaseUser, databasePassword);
}
Hope this helps someone.
I had the same problem with Transparent Activation and Persistence in java. I managed to get it to work cleaning the database and starting from scratch. However, no works by calling commit() after changing the object graph. You must call store() on the root object.
This is a simple example:
/*************** Item.java ******************************************/
import com.db4o.activation.ActivationPurpose;
import com.db4o.activation.Activator;
import com.db4o.collections.ActivatableSupport;
import com.db4o.ta.Activatable;
public class Item implements Activatable {
private String name;
private transient Activator activator;
public Item(String name) {
this.name = name;
}
public String getName() {
activate(ActivationPurpose.READ);
return name;
}
public void setName(String name) {
activate(ActivationPurpose.WRITE);
this.name = name;
}
#Override
public String toString() {
activate(ActivationPurpose.READ);
return "Item [name=" + name + "]";
}
public void activate(ActivationPurpose purpose) {
ActivatableSupport.activate(this.activator, purpose);
}
public void bind(Activator activator) {
this.activator = ActivatableSupport.validateForBind(this.activator, activator);
}
}
/******************* Container.java *********************************/
import java.util.Set;
import com.db4o.activation.ActivationPurpose;
import com.db4o.activation.Activator;
import com.db4o.collections.ActivatableHashSet;
import com.db4o.collections.ActivatableSupport;
import com.db4o.ta.Activatable;
public class Container implements Activatable {
private String name;
private Set<Item> items;
private transient Activator activator;
public Container() {
items = new ActivatableHashSet<Item>();
}
public String getName() {
activate(ActivationPurpose.READ);
return name;
}
public void setName(String name) {
activate(ActivationPurpose.WRITE);
this.name = name;
}
public void addItem(Item item) {
activate(ActivationPurpose.WRITE);
items.add(item);
}
public Set<Item> getItems() {
activate(ActivationPurpose.READ);
return items;
}
#Override
public String toString() {
activate(ActivationPurpose.READ);
return "Container [items=" + items + "]";
}
public void activate(ActivationPurpose purpose) {
ActivatableSupport.activate(this.activator, purpose);
}
public void bind(Activator activator) {
this.activator = ctivatableSupport.validateForBind(this.activator, activator);
}
}
/************* Main.java ********************************************/
import com.db4o.Db4oEmbedded;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.config.EmbeddedConfiguration;
import com.db4o.ta.TransparentActivationSupport;
import com.db4o.ta.TransparentPersistenceSupport;
public class Main {
public static void main() {
EmbeddedConfiguration config = Db4oEmbedded.newConfiguration();
config.common().add(new TransparentActivationSupport());
config.common().add(new TransparentPersistenceSupport());
ObjectContainer db = Db4oEmbedded.openFile(config, System.getProperty("user.home") + "/testTP.db4o");
Container c = new Container();
c.setName("Container0");
ObjectSet<Container> result = db.queryByExample(c);
if(result.hasNext()) {
c = result.next();
System.out.println(c);
}
c.addItem(new Item("Item" + c.getItems().size()));
db.store(c);
System.out.println(c);
db.close();
}
}