Why does my History.newItem(someToken) not fire onValueChange()? - gwt

Even though it is correctly fired when I use History.fireCurrentHistoryState();
EDIT: All classes in the same package. Code updated -
TestHistory.java
public class TestHistory implements EntryPoint, ValueChangeHandler<String> {
static boolean isLoggedIn = false;
static final String PAGENAME = "mainscreen";
public void onModuleLoad()
{
History.addValueChangeHandler(this);
String startToken = History.getToken();
System.out.println("onModuleLoad Called..... start token= -------"+startToken+"--------");
if(!startToken.isEmpty())
History.newItem(startToken);
History.fireCurrentHistoryState(); //to execute onValueChange 1st time since 1st time history is not setup
}
#Override
public void onValueChange(ValueChangeEvent<String> event) {
String token = event.getValue();
String args = "";
int question = token.indexOf("?");
if (question != -1) {
args = token.substring(question + 1);
token = token.substring(0, question);
}
if(!isLoggedIn)
{
if(token.isEmpty() || "login".equals(token)) //1st time opened the site normally
new Login().display(false, RootPanel.get());
else {
new Login().display(true, RootPanel.get());
}
}
else //User has logged in
{
if(token.isEmpty() || "login".equals(token))
{
if(isLoggedIn)
Window.alert("Ur already logged in!!!");
else
new Login().display(false, RootPanel.get());
}
else if("withdraw".equals(token))
new Withdraw().display(RootPanel.get(), args);
else if("deposit".equals(token))
new Deposit().display(RootPanel.get(), args);
else //token not clear
Window.alert("Unrecognized token=" + token);
}
}
}
Login.java
public class Login {
static final String PAGENAME = "login";
void display(final boolean hasTypedSomeToken, Panel myPanel) //Process login
{
System.out.println("login display called");
Label displayLabel = new Label("This is the Login Page");
Label enterName = new Label("Enter ur name");
final TextBox txtName = new TextBox();
Label enterPasswd = new Label("Enter ur Passwd");
final TextBox txtPasswd = new TextBox();
Button btnLogIn = new Button("Login", new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
/* Real app will check DB. Here we r jst chckng d txt fields hv value */
if(txtName.getValue().length()>0 && txtPasswd.getValue().length()>0)
{
TestHistory.isLoggedIn = true;
if(hasTypedSomeToken) {
//History.back(); //send him to the URL(token) he bookmarked b4 loggin in
History.newItem("login",false);
History.back();
System.out.println(History.getToken());
}
else{
myPanel.clear();
Label displayLabel = new Label("Thank U for logging.);
myPanel.add(displayLabel);
}
}
}
});
myPanel.clear();
myPanel.add(displayLabel);
myPanel.add(enterName);
myPanel.add(txtName);
myPanel.add(enterPasswd);
myPanel.add(txtPasswd);
myPanel.add(btnLogIn);
}
}
Deposit.java
public class Deposit {
static final String PAGENAME = "deposit";
void display(Panel myPanel, String param)
{
System.out.println("deposit display called");
myPanel.clear();
Label displayLabel = new Label("This is the Deposit Page & ur parameter = "+param+")");
myPanel.add(displayLabel);
}
}
Withdraw.java
//similar to deposit.java

The problem was with the usage of History.newItem(). the problem was occuring when I was using the bookmarked url and calling History.newItem() with a new token. Since already a token was present for the same internal page and I was giving it a new token so there was some confusion and onValueChange() was not being called.
Now Im clear that History.newItem() should be used when there is no token attached to the current view to mark the view with a token. Generally when a user opens a site normally (with no token), we should use history.newItem to mark the 1st view.
Also worth noting is that History.fireCurrentHistoryState() just calls onValueChange with the current token. And by going through the GWT's Code I found that History.newItem() simply calls History.fireCurrentHistoryState()
Actually if I replace
if(!startToken.isEmpty())
History.newItem(startToken);
History.fireCurrentHistoryState();
in my code with
if(startToken.isEmpty())
History.newItem("login");
else
History.fireCurrentHistoryState();
& also the code
if(hasTypedSomeToken) {
//History.back(); //send him to the URL(token) he bookmarked b4 loggin in
History.newItem("login",false);
History.back();
System.out.println(History.getToken());
}
with
if(hasTypedSomeToken) {
History.fireCurrentHistoryState();
System.out.println("getToken() in Login = "+History.getToken());
}
it works pretty well.

Although newItem(...) generally fires an event, it is a no-op if the current token is the same as the one you're trying to add. If that's not the case, there's a problem with your implementation.

Related

VisualForce Button not returning Selected Ids

I am converting a custom List JS button to support lighting. So, I've made changes to existing class and created a VF page and added that to the list view button. But when I run the functionality nothing seems to happen and debug logs returned Id as 000000.. Pls suggest.
global class AddUserToTeam{
public Opportunity objOpp;
global AddUserToTeam(ApexPages.StandardSetController stdcontroller) {
objOpp = (Opportunity)stdController.getRecord();
system.debug(objOpp );
}
public pagereference addTeam(){
List<Id> opportunityIds = new List<Id>();
opportunityIds.add(objOpp.Id);
system.debug('oppid'+ opportunityIds);
addTeamMember(opportunityIds);
//return new pagereference(url.getsalesforcebaseurl().toexternalform()+'/'+objOpp.Id);
return new PageReference('/006/o');
}
webservice static boolean addTeamMember(List<Id> opptyIds)
{
// some logic to add a user to teams
}
VF
<apex:page standardController="Opportunity" recordSetVar="Opportunities" extensions="AddUserToTeam" action="{!addTeam}">
</apex:page>
[enter image description here][1]
[1]: https://i.stack.imgur.com/2V3vp.png
I fixed the issue, check the below code
global class AddUserToTeam{
public Opportunity objOpp;
public String accIds{get;set;}
global AddUserToTeam(ApexPages.StandardSetController stdcontroller) {
System.debug('Get Selected');
objOpp = stdcontroller.getSelected();
accIds = '';
for(Opportunity acc : objOpp){
accIds += acc.Id + ',';
System.debug('Opp ID : '+accIds);
}
accIds = accIds.removeEnd(',');
}
}
public pagereference addTeam(){
List<Id> opportunityIds = new List<Id>();
opportunityIds.add(accIds );
system.debug('oppid'+ opportunityIds);
addTeamMember(opportunityIds);
return new pagereference(url.getsalesforcebaseurl().toexternalform()+'/'+accIds );
//return new PageReference('/006/o');
}
webservice static boolean addTeamMember(List<Id> opptyIds)
{
// some logic to add a user to teams
}

Wicket 7 - AutoCompleted Text field - to have onSelect method

We would like to implement AutoCompleteTextField field, once user has selected the field from AutoComplete result, then system would auto populate on other text field, i have used the component AjaxFormComponentUpdatingBehavior (blur), however this will take effect on every text input from AutoCompleteTextField field, but if i change to AjaxFormComponentUpdatingBehavior (change), it doesnt work.
Below is the sample code:
AutoCompleteTextField<String> field_postcode = new AutoCompleteTextField<String>("field_postcode",
new PropertyModel<String>(getModelObject(), "wAdditionalInfo.postal"), autoCompleteRenderer) {
private static final long serialVersionUID = 1L;
#Override
protected Iterator<String> getChoices(String input) {
if (Strings.isEmpty(input)) {
List<String> emptyList = Collections.emptyList();
return emptyList.iterator();
}
List<String> choices = new ArrayList<String>();
List<Postcode> postcodeList = getProfileManager().findAllPostcodeByPostcode(input);
for (Postcode p : postcodeList) {
String postcode = p.getPostcode();
if (postcode.startsWith(input)) {
choices.add(p.getPostcode());
if (choices.size() == 10) {
break;
}
}
}
return choices.iterator();
}
};
field_postcode.setRequired(true);
field_postcode.add(new AjaxFormComponentUpdatingBehavior("blur"){
private static final long serialVersionUID=-1107858522700306810L;
#Override protected void onUpdate( AjaxRequestTarget target){
Postcode postcode = getProfileManager().findPostcodeByPostcode(field_postcode.getInput());
if (postcode != null) {
City city = postcode.getCity();
State state = city.getState();
field_city.setModelObject(city.getCity());
ddl_state.setModelObject(state);
if (isDisplayTip) {
//isDisplayTip true mean is from widrawal webform
isReadonly = true;
} else {
field_city.setEnabled(false);
}
ddl_state.setEnabled(false);
} else {
if (isDisplayTip) {
isReadonly = false;
} else {
field_city.setEnabled(true);
}
ddl_state.setEnabled(true);
}
target.add(field_city, ddl_state);
}
}
);
Is there any api from wicket to achieve this? We need to have something when user select the option from Auto complete, then it only onUpdate method of AjaxFormComponentUpdatingBehavior
According to https://github.com/apache/wicket/blob/cbc237159c4c6632b4f7db893c28ab39d1b40ed4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js#L620 it should trigger change event on the HTMLInputElement and thus notify you on the server side.
Use the browser debugger to see whether https://github.com/apache/wicket/blob/cbc237159c4c6632b4f7db893c28ab39d1b40ed4/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/wicket-autocomplete.js#L453 is executed and whether it leads to an Ajax call with the value in the parameters.

Android WebView in a ViewSwitcher loadUrl loads once

I have in my ViewSwitcher a ListView and a WebView. In my ListView's adapter, I have an onclick listener that writes the clicked url in the list to sharedpreferences. I'm trying to load that url into the WebView using an onSharedPreferencesChangedListener.
This is the code in my adapter:
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewSwitcher.showNext();
Settings.writeSettings(context, "webviewUrl",
urls.get(position));
}
});
return convertView;
And in the preference listener:
#Override
public void onSharedPreferenceChanged(SharedPreferences pref, String key) {
if (key.equals("webviewUrl")) {
Log.d("TAG", pref.getString(key, null));
WebView wv = (WebView) findViewById(R.id.rss_webview);
wv.getSettings().setJavaScriptEnabled(true);
wv.setWebViewClient(new MyWebViewClient());
wv.loadUrl("about:blank");
wv.loadUrl(pref.getString(key, null));
}
}
This works great except it only works once. The preference listener code logs the correct urls, and the code executes each time I want it to, but wv.loadUrl() method seems to do nothing after the first successful call. Can anyone explain to me why this is happening and perhaps offer a solution? Thanks.
I solved the problem by implementing a static ViewHolder on the WebView whose reference I needed to keep longer than its views' lifecycle.
private static final class WebViewHolder {
WebView wv;
}
#Override
public void onSharedPreferenceChanged(SharedPreferences pref, String key) {
WebViewHolder holder = new WebViewHolder();
if (key.equals("webviewUrl")) {
if (wv == null) {
wv = new WebView(this);
holder.wv = (WebView) findViewById(R.id.rss_webview);
holder.wv.getSettings().setJavaScriptEnabled(true);
holder.wv.setWebViewClient(new MyWebViewClient());
wv.setTag(holder);
} else {
holder = (WebViewHolder) wv.getTag();
}
holder.wv.loadUrl("about:blank");
holder.wv.loadUrl(pref.getString(key, null));
}
}

confusion in running small history GWT application

When I am running a small login application consisting of history management, it works fine at my home where im using latest chrome and firefox versions and GWT 2.4
The same application when I run at my office works wild. I have used a Global static boolean variable which has correct value in the debug mode while it has wrong value when I run it normally. In Office Im using IE 7 and GWT 2.2
Also, onModuleLoad() is called only once at my home environment whereas it is called everytime when I type someURL#sometoken and press enter to change the internal page. When is onModuleLoad() called. Only once per session or evrytime user loads some page (or even token)?
Can anyone tell is this some problem due to IE 7 or GWT 2.2 or some other issue.
EDIT - Its very small app. Code ---
TestHistory.java
public class TestHistory implements EntryPoint, ValueChangeHandler<String> {
static boolean isLoggedIn = false;
static final String PAGENAME = "mainscreen";
public void onModuleLoad()
{
History.addValueChangeHandler(this);
String startToken = History.getToken();
System.out.println("onModuleLoad Called..... start token= -------"+startToken+"--------");
if(startToken.isEmpty())
History.newItem("login");
else
History.fireCurrentHistoryState(); //to execute onValueChange 1st time since 1st time history is not setup
}
#Override
public void onValueChange(ValueChangeEvent<String> event) {
String token = event.getValue();
System.out.println("onValueChange called with token = ***"+token+"***");
String args = "";
int question = token.indexOf("?");
if (question != -1) {
args = token.substring(question + 1);
token = token.substring(0, question);
}
if(!isLoggedIn)
{
if(token.isEmpty() || "login".equals(token)) //1st time opened the site normally
new Login().display(false, RootPanel.get());
else {
new Login().display(true, RootPanel.get());
}
}
else //User has logged in
{
if(token.isEmpty() || "login".equals(token))
{
if(isLoggedIn)
Window.alert("Ur already logged in!!!");
else
new Login().display(false, RootPanel.get());
}
else if("withdraw".equals(token))
new Withdraw().display(RootPanel.get(), args);
else if("deposit".equals(token))
new Deposit().display(RootPanel.get(), args);
else //token not clear
Window.alert("Unrecognized token=" + token);
}
}
}
Login.java
public class Login {
static final String PAGENAME = "login";
void display(final boolean hasTypedSomeToken,final Panel myPanel) //Process login
{
System.out.println("login display called");
Label displayLabel = new Label("This is the Login Page");
Label enterName = new Label("Enter ur name");
final TextBox txtName = new TextBox();
Label enterPasswd = new Label("Enter ur Passwd");
final TextBox txtPasswd = new TextBox();
Button btnLogIn = new Button("Login", new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
/* Real app will check DB. Here we r jst chckng d txt fields hv value */
if(txtName.getValue().length()>0 && txtPasswd.getValue().length()>0)
{
TestHistory.isLoggedIn = true;
if(hasTypedSomeToken) {
System.out.println("adsljasdlfjljkfsd");
History.fireCurrentHistoryState();
System.out.println("hoolala "+History.getToken());
}
else
{
myPanel.clear();
Label displayLabel = new Label("Thank U for logging. U can now access the application.");
myPanel.add(displayLabel);
}
}
}
});
myPanel.clear();
myPanel.add(displayLabel);
myPanel.add(enterName);
myPanel.add(txtName);
myPanel.add(enterPasswd);
myPanel.add(txtPasswd);
myPanel.add(btnLogIn);
}
}
Deposit.java
public class Deposit {
static final String PAGENAME = "deposit";
void display(Panel myPanel, String param)
{
System.out.println("deposit display called");
myPanel.clear();
Label displayLabel = new Label("This is the Deposit Page & ur parameter = "+param+")");
myPanel.add(displayLabel);
}
}
Class Withdraw is same as Deposit.
The problem Im facing is that once Im logged in I should be able to open all the internal pages which works perfectly at my home (and onModuleLoad() is called just once) whereas I have to log in everytime to open a internal page at my office (and onModuleLoad() is called evrytime)
onModuleLoad is called when the page is loaded, but:
pressing the enter key while in the address bar can reload the page in some browsers
changing the hash in the URL from outside the application (typing in the address bar, or using a bookmark) can confuse IE6/7; when GWT detects it, it reloads the page (have a look inside the HistoryImplIE6 class). Note that it does not happen when navigating in the history (this is what the hidden iframe is for)
Did you included the hidden iframe for history support in gwt in your html host page?
See http://code.google.com/intl/de-DE/webtoolkit/doc/latest/DevGuideCodingBasicsHistory.html#mechanism

Trying to Add More tabs to tab panel upon clicking on a button

I would like to add more tabs to the tab panel upon receiving a reponse from a servelet.. the problem is that It only adds the last one and not the the others see part of the code below. It seems like it is only adding the last panel "Time Reports" but not the other two
Thank you
btnLogin.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
if(getLoginResult())
{
HorizontalPanel temp = new HorizontalPanel();
panel.add(temp, "Add Hours");
panel.add(temp, "Time Sheets");
panel.add(temp, "Time Reports");
}
}
});
RootPanel.get().add(panel);
}
private boolean getLoginResult() {
AsyncCallback callback = new AsyncCallback() {
public void onSuccess(Object result) {
isAuthenticated = true;
}
public void onFailure(Throwable caught) {
Window.alert("Error when invoking the pageable data service :" + caught.getMessage());
isAuthenticated = false;
}
};
timesheetLoginServlet.isAuthenticated("1","rapidjava", callback);
return isAuthenticated;
}
}
You can add any widget to its parent only once. Change the temp to temp1, temp2 and temp3