Using tapestry5-jquery and Dialog component, ¿How do I implement a close action for the parent dialog?. I mean a button that executes some code and then close parent dialog without changing of page.
This is the javascript only version of what I'm doing:
<div id="container">
¿Are you sure to delete selected items?
</div>
$('#container').dialog({
modal : true,
buttons:[{
text: "Yes",
click: function() {
//Perform action here, then close dialog.
$(this).dialog("close");
}
},{
text: "No",
click: function() {
//Only close dialog
$(this).dialog("close");
}
}
}]
});
But I need to use Tapestry 5 tags and java class methods:
<t:jquery.dialog t:clientId="delDialog">
¿Are you sure to delete selected items?
<input t:type="submit" t:id="delYes" value="Yes"/>
<input t:type="submit" t:id="delNo" value="No"/>
</t:jquery.dialog>
Java class:
public class UserAdmin {
#OnEvent(component = "delYes", value = EventConstants.SELECTED)
void delYesClicked(){
//Delete selected items
}
#OnEvent(component = "delNo", value = EventConstants.SELECTED)
void delNoClicked(){
//Close dialog
}
}
Thanks.
You could do something like this if the clientId is always the same (i.e. 'delDialog')
#Inject
private AjaxResponseRenderer ajaxResponseRenderer;
protected void addCloseDialogCommand() {
ajaxResponseRenderer.addCallback(new JavaScriptCallback() {
#Override
public void run(JavaScriptSupport javascriptSupport) {
javascriptSupport.addScript("$('#delDialog').dialog('close');");
}
});
}
...and call the method in your event handler:
#OnEvent(component = "delNo", value = EventConstants.SELECTED)
void delNoClicked() {
addCloseDialogCommand();
}
This behavior could be implemented using a mixin that you apply on any element you want.
Suggested mixin:
public class DialogButtonHandler {
#Parameter(value = "dlgId", defaultPrefix = BindingConstants.LITERAL)
private String dlgId;
#Inject
private JavaScriptSupport javaScriptSupport;
#InjectContainer
private ClientElement element;
#AfterRender
public void afterRender() {
javaScriptSupport.addScript(
"$('#%s').click(function(){$('#%s').dialog('close');});",
element.getClientId(), dlgId);
}}
Markup:
<t:jquery.dialog t:clientId="delDialog">
¿Are you sure to delete selected items?
<input t:type="submit" t:id="delYes" value="Yes" />
<input t:type="submit" t:id="delNo" value="No" t:mixins="dialogButtonHandler" t:dlgId="delDialog"/>
</t:jquery.dialog>
Related
I have list of notification, user can select list of notification and delete.
Delete process working fine but I have to reload page every time user delete item, I couldn't view the changes once user delete elements.
I have trying Angular detect changes but it doesn't work.
It looks like there is something prevent Angular functions from work.
My .ts page
async changeView(){
if(this.dataselect!=undefined){
if(this.dataselect!=""){
const alert = await this.alertCtrl.create({
message: this.removenoti,
buttons: [
{
text: "Cancel",
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}, {
text: "Remove",
handler: () => {
const SigninData = JSON.parse(localStorage.getItem("signindata"));
this.userData.id = SigninData.mem_id;
this.userData.token = SigninData.token;
this.userData.noti_id = this.dataselect;
console.log(this.userData.noti_id);
this.providersservices.postData(this.userData, "deletenoti2").subscribe((result) =>{
this.zone.runOutsideAngular(() => {
this.presentToast(this.removesuccess);
// executing inside NgZone
this.zone.run(() => {
this.dataselect="";
this.edit=false;
this.SelAll = false;
for(var i in this.items)
{
this.checkItems[this.items[i].id]=false;
}
});
console.log(result);
let loading_time = 2000;
setTimeout( () => {
this.ngOnInit();
}, loading_time);
// window.location.assign('/');
});
}, (err) => {
console.log(JSON.stringify(err));
this.presentToast("Please connect your device to internet!");
});
}
}
]
});
await alert.present();
} else {
this.presentToast(this.noitems);
}
} else {
this.presentToast(this.noitems);
}
}
My html code
<ion-content style="--padding-top:6em">
<ion-fab *ngIf="exist=='true'" class="header_tab">
<button ion-fab *ngIf="edit" class="cancelremove" style="right: 45px;" (click)="changeView()">
<ion-icon name="trash-outline"></ion-icon>
</button>
</ion-fab>
<div *ngIf="exist=='true'">
<ion-grid *ngFor="let item of items" class="list" >
<ion-row class="textin" *ngIf="item.nstatus!=1" [style.background-color]="hexColor2">
<ion-checkbox *ngIf="edit" [checked]="allSelected" [(ngModel)]="checkItems[item.id]" (ionChange)="DeSelect();DeSelectall(item.id)"></ion-checkbox>
<ion-label style="width: 100%;max-height: 4em;">
<ion-col col-12 (click)="view(item.id, item.nsubject, item.ndetail, item.ncompany, item.nphoto)">
<ion-row class="condate">
<ion-col col-7 style="padding-left:0;">
<div *ngIf="item.nid!=0">
<p class="titlenote">{{ item.ncompany}}</p>
</div>
<div *ngIf="item.nid==0">
<p class="titlenote">Tagy</p>
</div>
</ion-col>
<ion-col col-5>
<p class="date">{{ item.ndate| date:'dd/MM/yyyy hh:mm' }}</p>
</ion-col>
</ion-row>
<ion-row>
<ion-col col-12>
<p class="detailnote">{{ item.nsubject }}</p>
</ion-col>
</ion-row>
</ion-col>
</ion-label>
</ion-row>
</ion-grid>
</div>
In angular, you can use Observables and Behavior Subjects.
You can create them like this in the .ts file
activityLoaded$ = new BehaviorSubject(false);
this.activityLoaded$.next(true);
and use them with the async pipe in the html
*ngIf="(activityLoaded$ | async) === false"
As it is async, it will update itself everytime a new value will be pushed with .next method.
I'm sorry I don't have the time to perfectly adapt my answer to your question but now you at least know and can learn more about it.
Here is a 1st link on the subject:
https://angular.io/guide/observables
I remember seeing this kind of issue when I worked with Ionic for my mobile project. After fetching data from an API, to re-render the UI, we had to execute the code within NgZone for angular to call change detection. So try this inside your handler: () function:
this.providersservices.postData(this.userData, "deletenoti2").subscribe((result) => {
this.presentToast(this.removesuccess);
// executing inside NgZone
this.zone.run(() => {
this.dataselect="";
this.edit=false;
this.SelAll = false;
for(var i in this.items) {
this.checkItems[this.items[i].id]=false;
}
});
console.log(result);
}
As I do not have full visibility of your component's code, above code is my best assumption what should execute inside NgZone, based on the code sample you have provided.
Of course, to use NgZone, you have to import it and declare in the constructor:
constructor(
...
...
private zone: NgZone
) {}
Hope this helps!
You can try using the ChangeDetectorRef to ask angular to detect any changes.
example:
import { ChangeDetectorRef } from '#angular/core';
constructor(private cdr: ChangeDetectorRef) {}
deleteItem() {
this.cdr.markForCheck();
this.cdr.detectChanges();
}
I am new in GWT world, previously I was working with JavaScript. I have some web-page where are multiple element. And I need to track which element was clicked using GWT.
I am using GWT 2.8.1
<div class="FileRow">
</div>
<div class="FileRow">
</div>
<div class="FileRow">
</div>
GWT realization
Integer tabIndex = 1, count = 1;
for (final FieldFileInfo info : clientData.getFileInfo()) {
final FlowPanel rowPanel = new FlowPanel();
rowPanel.setStyleName("FileRow");
final HyperlinkPanel fileLink = FileInfoParser.getLinkPanel(info);
fileLink.setStyleName("fileLink");
fileLink.setTabIndex(tabIndex++);
fileLink.setText("");
switch (info.getFileExtension()) {
case "png" :
fileLink.addStyleName("png");
fileLink.getElement().setId("png");
break;
case "jpg" :
fileLink.addStyleName("jpg");
fileLink.getElement().setId("jpg"+count);
break;
case "pdf" :
fileLink.addStyleName("pdf");
fileLink.getElement().setId("pdf");
break;
default :
fileLink.addStyleName("file");
fileLink.getElement().setId("file");
}
rowPanel.add(fileLink);
count++;
}
click realization
Element openPng = Document.get().getElementById("png");
Event.sinkEvents(openPng, Event.ONCLICK);
Event.setEventListener(openPng, new OpenModalHandler());
Now my click realization works only on first element with required ID. However in future there might be several elements with the same id and as a result I could not alert another elements.
Expected result is when I click on first element, GWT using Window.alert() show which element was clicked.
The answer is really simple.
To track which element was clicked I just modified case with:
fileLink.addClickHandler(new ClickHandlerData<Integer>(tabIndex) {
public void onClick(ClickEvent event) {
Window.alert("You clicked on " getData());
}
});
Also implement new class with ClickHandlerData
public abstract class ClickHandlerData<I> implements ClickHandler {
private I data;
public ClickHandlerData(I data) {
this.data = data;
}
public I getData() {
return data;
}
public void setData(I data) {
this.data = data;
}
}
I am using GWT Java and I am trying to remove the PayPal Donate button (i.e., clear the RootPanel), which is part of an HTML form, when I move from the LoginView to another view. I found that I should use:
RootPanel.get("payPalDonate").clear();
RootPanel.get().clear();
RootPanel.get().getElement().setInnerHTML("");
This does clear the form so it does not appear on the next view; however, when the next view is displayed the buttons, hyperlinks and the browser back button on the view do not work.
The code is in the :
private void checkWithServerIfSessionIdIsStillLegal(String sessionID) {
rpc = (DBConnectionAsync) GWT.create(DBConnection.class);
ServiceDefTarget target = (ServiceDefTarget) rpc;
String moduleRelativeURL = GWT.getModuleBaseURL() + "MySQLConnection";
target.setServiceEntryPoint(moduleRelativeURL);
AsyncCallback<Account> callback = new AuthenticationHandler<Account>();
rpc.loginFromSessionServer(callback);
}
class AuthenticationHandler<T> implements AsyncCallback<Account> {
#Override
public void onFailure(Throwable caught) {
RootPanel.get().add(new LoginView());
}
#Override
public void onSuccess(Account result) {
if (result == null) {
RootPanel.get().add(new LoginView());
} else {
//if (result.getLoggedIn()) {
RootPanel.get().clear();
//RootPanel.get().add(new SelectPersonView());
RootPanel.get().add(new LoginView());
//} else {
//RootPanel.get().add(new LoginView());
//}
}
}
}
public void onValueChange(ValueChangeEvent<String> event) {
RootPanel.get("payPalDonate").clear();
RootPanel.get().clear();
RootPanel.get().getElement().setInnerHTML("");
//Get the historyToken value
String historyToken = event.getValue();
//Check the historyToken
if (historyToken.startsWith("!"))
historyToken = historyToken.substring(1);
if (historyToken.length() == 0) {
//Initial entry
RootPanel.get().clear();
RootPanel.get().add(new LoginView());
} else if (historyToken.equals("login")) {
RootPanel.get().clear();
RootPanel.get().add(new LoginView());
} else if (historyToken.equals("goToVideo")) {
RootPanel.get().clear();
Window.Location.replace("https://www.youtube.com/user/GlyndwrBartlett");
} else if (historyToken.equals("goToMetawerx")) {
RootPanel.get().clear();
Window.Location.replace("https://www.metawerx.net/");
} else if (historyToken.equals("goToPrivacy")) {
RootPanel.get().clear();
RootPanel.get().add(new SecurityAndPrivacyView());
} else if ...
In the LoginView:
initWidget(verticalPanel);
RootPanel.get("payPalDonate");
In the html:
<div style="margin:auto" id="payPalDonate">
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="image" src="https://www.paypalobjects.com/en_AU/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal – The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_AU/i/scr/pixel.gif" width="1" height="1">
</form>
</div>
Typically in GWT the RootPanel is never cleared. When you start your app, you pass a container to the RootPanel, and then all the views are added to and removed from that container.
Personally, I use Activities and Places pattern for all of my apps. This link offers an example of how to change views within a main container.
I am reading the link provided by Andrei. In the meantime I found the issues were being cased by:
RootPanel.get().getElement().setInnerHTML("");
I tried:
RootPanel.getBodyElement().removeChild(RootPanel.get("payPalDonate").getElement());
However, this cased the same issue. In the end I found this https://groups.google.com/forum/#!topic/google-web-toolkit/zVvY39blkY4
So I replaced the offending code with:
RootPanel.get("payPalDonate").setVisible(false);
And I placed the code in the LoginView just before I pass control to another view. Not the most elegant; however, it works until I digest the information provided by Andrei.
I have a view with the checkboxes
#for((jc)<-jobcategoryList) {
<input type="checkbox" name="jobcategory.id" value="#jc.id">#jc.name<br>
}
I just want to send this list of checked checkboxes to my controller.But on doing this
public class JobAdController extends Controller {
public static Result save() {
Form<Jobads> jobadsFormData = jobadsForm.bindFromRequest();
if (jobadsFormData.hasErrors()) {
System.out.println("Error in form");
return badRequest();
} else {
Jobads jads= jobadsFormData.get();
List<Jobcategories> jadsList= jads.getJobcategory();
System.out.print("\nLength is:"+jadsList.size());// always prints Length is:0
}}
}
where Jobads and Jobcategory are my models.
My Jabads.java model
public class Jobads extends Model {
#ManyToMany
private List<Jobcategories> jobcategories;
}
My problem is that whenever i submit my view form with the checkboxes(given above).My console prints Length is:0
When i tried to change my view to
#for((jc,index)<-jobcategoryList.zipWithIndex) {
<input type="checkbox" name="jobcategory[index]" value="#jc">#jc.name<br>
}
and submit my form the controller an [[NumberFormatException: For input string: "index"]] is generated on the first line of controller.
How can I send this checked boxes to my controller.
Thanks
Use:
#for(jc <- jobcategoryList) {
<input type="checkbox" name="jobcategories[]" value="#jc.id">#jc.name<br>
}
or
#for((jc,index) <- jobcategoryList.zipWithIndex) {
<input type="checkbox" name="jobcategories[#index]" value="#jc.id">#jc.name<br>
}
and in your form class:
public List<Long> jobcategories;
I'm trying to rerender a second dropdown when i change the value in the first one.
But nothing happens when I click and change the value in the first drop down.
Have I missed any crucial part?
My xhtml:
<h:form>
<h:selectOneMenu value="#{adminBean.currentLeadCategory}" required="true" styleClass="formfield fpgeo" style="width:20em;margin-right:20px;">
<a4j:support event="onchange" action="#{adminBean.currentLeadCategoryChanged()}"
reRender="componentToReRender"/>
<s:selectItems value="#{leadCategories}" var="leadCategory" label="#{leadCategory.name}" noSelectionLabel="Choose Category"/>
<s:convertEntity/>
</h:selectOneMenu>
<a4j:outputPanel id="componentToReRenderWrapper">
<h:selectOneMenu id="componentToReRender" value="#{adminBean.currentCounty}"
styleClass="formfield fpgeo" style="width:20em;margin-right:20px;">
<s:selectItems value="#{adminBean.counties}" var="county" label="#{county.name}" noSelectionLabel="choose"/>
<s:convertEntity/>
</h:selectOneMenu>
<h:messages/>
</a4j:outputPanel>
</h:form>
My bean:
#AutoCreate
#Scope(ScopeType.CONVERSATION)
#Name("adminBean")
#MeasureCalls
#Restrict("#{s:hasRole('admin') or s:hasRole('sales')}")
public class AdminBean implements Serializable {
private LeadCategory currentLeadCategory;
private List<County> counties = new ArrayList<County>();
private County currentCounty;
#Factory(value = "leadCategories", autoCreate = true, scope = ScopeType.SESSION)
public List<LeadCategory> fetchLeadCategories() {
Query query = entityManager.createQuery("select l from LeadCategory l");
return query.getResultList();
}
public LeadCategory getCurrentLeadCategory() {
return currentLeadCategory;
}
public void setCurrentLeadCategory(LeadCategory currentLeadCategory) {
this.currentLeadCategory = currentLeadCategory;
}
public County getCurrentCounty() {
return currentCounty;
}
public void setCurrentCounty(County currentCounty) {
this.currentCounty = currentCounty;
}
public void currentLeadCategoryChanged() {
this.loadCountiesForCategory();
}
public List<County> getCounties() {
return counties;
}
public void setCounties(List<County> counties) {
this.counties = counties;
}
public void loadCountiesForCategory(){
if(currentLeadCategory == null){
counties = new ArrayList<County>();
}
counties = new ArrayList<County>(currentLeadCategory.getCounties());
}
}
EDIT 1:
If i check firebug i get an error:
Timestamp: 7/19/12 4:14:44 PM
Error: ReferenceError: A4J is not defined
Source File: http://localhost:8080/admin/admin.seam?cid=11
Line: 1
Ok found the problem! Major crazyness going on here. Someone has set LoadScriptStrategy
param to NONE in the web.xml. This makes that the framework.pack.js and ui.pack.js is NOT loading.
<context-param>
<param-name>org.richfaces.LoadScriptStrategy</param-name>
<param-value>NONE</param-value>
</context-param>
Found this page at docs.jboss
If you use the "NONE" strategy, you must include the following scripts
in your portlet or portal page header. If you are using JBoss Portal,
you can add this to the jboss-portlet.xml file.
Added <a4j:loadScript src="resource:///org/ajax4jsf/framework.pack.js"/>
to my header template and viola everything works like a charm.
I love my job =)
I can see clearly that your xhtml has an ending tag </a4j:outputPanel> but no starting tag: <a4j:outputPanel>
If you rearrange your tags it will work.