The communication between client and server side is using JSON then you can use whatever language on the server side that produce a JSON output.
The source code is on github https://github.com/poseidonjm/GXT3-PHP is structured using GWTP and GWT Editor for binding.
Database table
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
create table users( | |
id serial, | |
login varchar(60), | |
first varchar(150), | |
last varchar(150), | |
primary key(id) | |
); | |
insert into users(login, first, last)values('jacy','Jacinto','Miraval'); | |
insert into users(login, first, last)values('richard','Richard','Salazar'); | |
insert into users(login, first, last)values('marcelo','Marcelo','Bailón'); | |
insert into users(login, first, last)values('hector','Hector','Jara'); | |
insert into users(login, first, last)values('jose','Jose','Ventura'); |
GXT and HttpProxy
First of all the next interfaz and class are required
MyAutoBeanFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.crud.shared.util; | |
import com.google.web.bindery.autobean.shared.AutoBean; | |
import com.google.web.bindery.autobean.shared.AutoBeanFactory; | |
import com.sencha.gxt.data.shared.SortInfo; | |
import com.sencha.gxt.data.shared.loader.FilterConfig; | |
import com.sencha.gxt.data.shared.loader.FilterPagingLoadConfig; | |
public interface MyAutoBeanFactory extends AutoBeanFactory { | |
AutoBean<FilterPagingLoadConfig> loadConfig(); | |
AutoBean<SortInfo> getSortInfo(); | |
AutoBean<FilterConfig> getFilterConfig(); | |
} |
MyHttpProxy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.crud.shared.util; | |
import java.util.ArrayList; | |
import java.util.List; | |
import com.google.gwt.http.client.RequestBuilder; | |
import com.sencha.gxt.data.client.loader.HttpProxy; | |
import com.sencha.gxt.data.shared.SortInfo; | |
import com.sencha.gxt.data.shared.loader.FilterConfig; | |
public class MyHttpProxy<C> extends HttpProxy<C> { | |
public MyHttpProxy(RequestBuilder builder) { | |
super(builder); | |
} | |
protected List<SortInfo> createRequestSortInfo(MyAutoBeanFactory factory, List<? extends SortInfo> original) { | |
List<SortInfo> sortInfo = new ArrayList<SortInfo>(); | |
for (int i = 0; i < original.size(); i++) { | |
SortInfo originalSortInfo = original.get(i); | |
SortInfo reqSortInfo = factory.getSortInfo().as(); | |
reqSortInfo.setSortDir(originalSortInfo.getSortDir()); | |
reqSortInfo.setSortField(originalSortInfo.getSortField()); | |
sortInfo.add(reqSortInfo); | |
} | |
return sortInfo; | |
} | |
protected List<FilterConfig> createRequestFilterConfig(MyAutoBeanFactory factory, List<? extends FilterConfig> original) { | |
List<FilterConfig> sortInfo = new ArrayList<FilterConfig>(); | |
for (int i = 0; i < original.size(); i++) { | |
FilterConfig originalSortInfo = original.get(i); | |
FilterConfig reqSortInfo = factory.getFilterConfig().as(); | |
reqSortInfo.setComparison(originalSortInfo.getComparison()); | |
reqSortInfo.setField(originalSortInfo.getField()); | |
reqSortInfo.setType(originalSortInfo.getType()); | |
reqSortInfo.setValue(originalSortInfo.getValue()); | |
sortInfo.add(reqSortInfo); | |
} | |
return sortInfo; | |
} | |
} |
GWT AutoBean
With GWT AutoBean is easy to serialize/deserialize GWT Objects to json and vice versa,
on the client side there is the UserProxy interface that represents the model
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.crud.shared.proxy; | |
public interface UserProxy { | |
String getFirst(); | |
void setFirst(String first); | |
String getLast(); | |
void setLast(String last); | |
String getLogin(); | |
void setLogin(String login); | |
Long getId(); | |
void setId(Long id); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.crud.shared.listproxy; | |
import java.util.List; | |
import com.crud.shared.proxy.UserProxy; | |
public interface UserListProxy { | |
List<UserProxy> getData(); | |
int getTotalCount(); | |
void setData(List<UserProxy> data); | |
} |
With AutoBean the objects are created from a factory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.crud.shared.factory; | |
import com.crud.shared.listproxy.UserListProxy; | |
import com.crud.shared.proxy.UserProxy; | |
import com.crud.shared.util.MyAutoBeanFactory; | |
import com.google.web.bindery.autobean.shared.AutoBean; | |
public interface AppAutoBeanFactory extends MyAutoBeanFactory { | |
AutoBean<UserListProxy> users(); | |
AutoBean<UserProxy> newUser(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Create a object | |
UserProxy user = factory.newUser().as(); | |
//Serialize an object | |
AutoBean<UserProxy> bean = AutoBeanUtils.getAutoBean(user); | |
String json = AutoBeanCodex.encode(bean).getPayload(); | |
//Send to server | |
String path = "users/users.php?action=save"; | |
RequestBuilder builder = new RequestBuilder(RequestBuilder.PUT, path); | |
try { | |
builder.sendRequest(json, new RequestCallback() { | |
@Override | |
public void onResponseReceived(Request request, Response response) { | |
Info.display("Users", "Save Successful"); | |
getView().load(); | |
} | |
@Override | |
public void onError(Request request, Throwable exception) { | |
} | |
}); | |
} catch (RequestException e) { | |
e.printStackTrace(); | |
} |
GXT Grid use a reader to parse the output of the server.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.crud.shared.jsonreader; | |
import com.crud.shared.listproxy.UserListProxy; | |
import com.crud.shared.proxy.UserProxy; | |
import com.google.web.bindery.autobean.shared.AutoBeanFactory; | |
import com.sencha.gxt.data.shared.loader.FilterPagingLoadConfig; | |
import com.sencha.gxt.data.shared.loader.JsonReader; | |
import com.sencha.gxt.data.shared.loader.PagingLoadResult; | |
import com.sencha.gxt.data.shared.loader.PagingLoadResultBean; | |
public class UserJsonReader extends JsonReader<PagingLoadResult<UserProxy>, UserListProxy> { | |
public UserJsonReader(AutoBeanFactory factory, | |
Class<UserListProxy> rootBeanType) { | |
super(factory, rootBeanType); | |
} | |
@Override | |
protected PagingLoadResult<UserProxy> createReturnData(Object loadConfig, UserListProxy incomingData) { | |
FilterPagingLoadConfig pagingLoadConfig = (FilterPagingLoadConfig)loadConfig; | |
return new PagingLoadResultBean<UserProxy>(incomingData.getData(), incomingData.getTotalCount(), pagingLoadConfig.getOffset()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class UserView extends ViewImpl implements UserPresenter.MyView { | |
interface UserProxyProperties extends PropertyAccess<UserProxy> { | |
ModelKeyProvider<UserProxy> id(); | |
ValueProvider<UserProxy, String> login(); | |
ValueProvider<UserProxy, String> first(); | |
ValueProvider<UserProxy, String> last(); | |
} | |
private final Widget widget; | |
public interface Binder extends UiBinder<Widget, UserView> { | |
} | |
private ListStore<UserProxy> store; | |
private PagingLoader<FilterPagingLoadConfig, PagingLoadResult<UserProxy>> loader; | |
@UiField(provided = true) | |
Grid<UserProxy> grid; | |
@UiField(provided = true) | |
PagingToolBar pagToolBar; | |
@UiField | |
ContentPanel panel; | |
@UiField | |
TextButton add; | |
@UiField | |
TextButton edit; | |
@UiField | |
TextButton delete; | |
UserProxy user; | |
@Inject | |
public UserView(final Binder binder) { | |
final AppAutoBeanFactory factory = GWT.create(AppAutoBeanFactory.class); | |
UserJsonReader reader = new UserJsonReader(factory, UserListProxy.class); | |
String path = "users/users.php"; | |
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, path); | |
MyHttpProxy<FilterPagingLoadConfig> proxy = new MyHttpProxy<FilterPagingLoadConfig>(builder){ | |
@Override | |
public void load(FilterPagingLoadConfig loadConfig, | |
Callback<String, Throwable> callback) { | |
List<SortInfo> sortInfo = createRequestSortInfo(factory, loadConfig.getSortInfo()); | |
List<FilterConfig> filterConfig = createRequestFilterConfig(factory, loadConfig.getFilters()); | |
loadConfig.setSortInfo(sortInfo); | |
loadConfig.setFilters(filterConfig); | |
super.load(loadConfig, callback); | |
} | |
}; | |
//proxy.setWriter(new UrlEncodingWriter<FilterPagingLoadConfig>(factory, FilterPagingLoadConfig.class)); | |
proxy.setWriter(new JsonWriter<FilterPagingLoadConfig>(factory, FilterPagingLoadConfig.class)); | |
loader = new PagingLoader<FilterPagingLoadConfig, PagingLoadResult<UserProxy>>(proxy, reader){ | |
@Override | |
protected FilterPagingLoadConfig newLoadConfig() { | |
return new FilterPagingLoadConfigBean(); | |
} | |
}; | |
loader.setRemoteSort(true); | |
loader.useLoadConfig(factory.loadConfig().as()); | |
UserProxyProperties props = GWT.create(UserProxyProperties.class); | |
store = new ListStore<UserProxy>(props.id()); | |
loader.addLoadHandler(new LoadResultListStoreBinding<FilterPagingLoadConfig, UserProxy, PagingLoadResult<UserProxy>>(store)); | |
pagToolBar = new PagingToolBar(3); | |
pagToolBar.bind(loader); | |
pagToolBar.getElement().getStyle().setProperty("borderBottom", "none"); | |
IdentityValueProvider<UserProxy> identity = new IdentityValueProvider<UserProxy>(); | |
final CheckBoxSelectionModel<UserProxy> sm = new CheckBoxSelectionModel<UserProxy>(identity); | |
sm.setSelectionMode(SelectionMode.MULTI); | |
ColumnConfig<UserProxy, String> usuarioColumn = new ColumnConfig<UserProxy, String>(props.login(), 80, "User Name"); | |
ColumnConfig<UserProxy, String> nombresColumn = new ColumnConfig<UserProxy, String>(props.first(), 150, "First Name"); | |
ColumnConfig<UserProxy, String> apellidosColumn = new ColumnConfig<UserProxy, String>(props.last(), 150, "Last Name"); | |
List<ColumnConfig<UserProxy, ?>> l = new ArrayList<ColumnConfig<UserProxy, ?>>(); | |
l.add(sm.getColumn()); | |
l.add(usuarioColumn); | |
l.add(nombresColumn); | |
l.add(apellidosColumn); | |
ColumnModel<UserProxy> cm = new ColumnModel<UserProxy>(l); | |
grid = new Grid<UserProxy>(store, cm) { | |
@Override | |
protected void onAfterFirstAttach() { | |
super.onAfterFirstAttach(); | |
Scheduler.get().scheduleDeferred(new ScheduledCommand() { | |
public void execute() { | |
loader.load(); | |
} | |
}); | |
} | |
}; | |
grid.setLoader(loader); | |
grid.setSelectionModel(sm); | |
grid.getView().setStripeRows(true); | |
GridFilters<UserProxy> filters = new GridFilters<UserProxy>(loader); | |
filters.initPlugin(grid); | |
filters.setLocal(false); | |
filters.addFilter(new StringFilter<UserProxy>(props.login())); | |
filters.addFilter(new StringFilter<UserProxy>(props.first())); | |
filters.addFilter(new StringFilter<UserProxy>(props.last())); | |
grid.getSelectionModel().addSelectionChangedHandler(new SelectionChangedHandler<UserProxy>() { | |
public void onSelectionChanged( | |
SelectionChangedEvent<UserProxy> event) { | |
int size = event.getSelection().size(); | |
if(size == 0){ | |
edit.setEnabled(false); | |
delete.setEnabled(false); | |
user = null; | |
}else if(size == 1){ | |
edit.setEnabled(true); | |
delete.setEnabled(true); | |
user = event.getSelection().get(0); | |
}else if(size > 1){ | |
edit.setEnabled(false); | |
delete.setEnabled(true); | |
user = null; | |
} | |
} | |
}); | |
widget = binder.createAndBindUi(this); | |
} | |
@Override | |
public Widget asWidget() { | |
return widget; | |
} | |
} |
UserView.ui.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> | |
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' | |
xmlns:g='urn:import:com.google.gwt.user.client.ui' | |
xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client" | |
xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container" | |
xmlns:toolbar="urn:import:com.sencha.gxt.widget.core.client.toolbar" | |
xmlns:button="urn:import:com.sencha.gxt.widget.core.client.button" | |
xmlns:grid="urn:import:com.sencha.gxt.widget.core.client.grid"> | |
<ui:with type="com.crud.client.resources.Resources" field="resources" /> | |
<ui:with field="verticalLayoutData" type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" > | |
<ui:attributes width="1" height="-1" /> | |
</ui:with> | |
<ui:with field="centerLayoutData" type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" > | |
<ui:attributes width="1" height="1" /> | |
</ui:with> | |
<gxt:ContentPanel headerVisible="false" borders="false" bodyBorder="false" > | |
<gxt:ContentPanel ui:field="panel" headingText="Users" > | |
<container:VerticalLayoutContainer> | |
<container:child layoutData="{verticalLayoutData}"> | |
<toolbar:ToolBar ui:field="toolBar"> | |
<button:TextButton text="Add" ui:field="add" icon="{resources.add}" /> | |
<toolbar:SeparatorToolItem /> | |
<button:TextButton text="Edit" ui:field="edit" icon="{resources.edit}" enabled="false" /> | |
<toolbar:SeparatorToolItem /> | |
<button:TextButton text="Delete" ui:field="delete" icon="{resources.delete}" enabled="false" /> | |
</toolbar:ToolBar> | |
</container:child> | |
<container:child layoutData="{centerLayoutData}" > | |
<grid:Grid ui:field="grid" /> | |
</container:child> | |
<container:child layoutData="{verticalLayoutData}"> | |
<toolbar:PagingToolBar ui:field="pagToolBar" /> | |
</container:child> | |
</container:VerticalLayoutContainer> | |
</gxt:ContentPanel> | |
</gxt:ContentPanel> | |
</ui:UiBinder> |
Run the proyect
You have to start your Apache Server and enable the following extensions for PostgreSQL and PDO:
php_pdo_pgsql
php_pgsql
You have to set the root of your web server to the war of the project
for example I use XAMPP and change the httpd.conf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
#DocumentRoot "C:/xampp/htdocs" | |
DocumentRoot "D:\juan\workspace\proyectos\phpcrud\war" | |
... | |
# | |
# This should be changed to whatever you set DocumentRoot to. | |
# | |
<Directory "D:\juan\workspace\proyectos\phpcrud\war"> | |
... |
Set the parameters of connection to database PostgreSQL in war/config/connect.php
I usually work on Firefox for GWT DevMode
Compile GWT code to JS
I compile GWT with Google Plugin for Eclipse GPE
By default the compiled JS code is compressed.
Then enter the url http://localhost/phpcrud.html#users
The Server Side PHP
I use simple PHP and PDO
connect.php
users.php
paginate.php
Sorry if I am missing explain PHP code.
I hope you can use GWT with any backend and AutoBean is a nice feature of GWT.
Hi,
ResponderEliminarI tried to run your example but I have an exception in "createRequestFilterConfig", "original" is null.
Do you have an idea ?
Thks,
JB
Could you be more specific.
ResponderEliminarI use Eclipse Juno
I downloaded and imported the eclipse project using Egit.
I have the GPE(Google plugin for eclipse) only for GWT
I have a GWT 2.5 as SDK.
And tested with firefox in dev mode with the Google Developer Plugin and is OK.
Maybe you need configure the eclipse project.