Hi Isomorphic,
I implement a similar Master-Detail example that appear in Server Examples / Transactions, embedded in a similar schema of the Office Supply Items with Items Details that you use in the Applications – Office Supply Catalog.
The add and delete options is perfect. My problem is with update option.
When I create (add) a campo, I provide a campo data and add some division. If I want to delete some division, I don’t have any problem, makinga click in remove icon. My detail (ListGrid) has enabled the option canRemoveRecords.
When I remove (del) a campo, I select a row from header with, and click the right boton. Its run ok.
When I want to update a campo, I read a campo and division data, and display it. I can update a campo data without problems. But my problem is when I want to remove a previous detail records
(that exist in the database for that campo). The record is removed from database but the grid is not refresh. I read at detail the thread http://forums.smartclient.com/showthread.php?t=344&highlight=Start+empty+listgrid and I am try with autoSaveEdits (true and false) and saveAllEdits (true and false) without success.
I enclose the js and the DMI
isc.DataSource.create({
serverType:"generic",
fields:[
{
sqlType:"integer",
sqlLength:"10",
title:"Division",
primaryKey:true,
hidden:true,
name:"divisionId",
type:"sequence"
},
{
sqlType:"varchar",
sqlLength:"30",
title:"Nombre",
name:"nombre",
length:"30",
type:"text"
},
{
sqlType:"integer",
sqlLength:"10",
title:"Edad Minima",
name:"edadMinima",
required:true,
type:"number"
},
{
sqlType:"integer",
sqlLength:"10",
title:"Edad Maxima",
name:"edadMaxima",
required:true,
type:"number"
},
{
sqlType:"char",
sqlLength:"1",
title:"Nivel de Juego",
name:"nivel",
length:"1",
type:"text"
},
{
sqlType:"char",
sqlLength:"1",
title:"Sexo",
name:"sexo",
length:"1",
type:"text"
},
{
sqlType:"integer",
sqlLength:"10",
title:"Minimo # Jugadores",
name:"minimoJugadores",
type:"number"
},
{
sqlType:"integer",
sqlLength:"10",
title:"Maximo # Jugadores",
name:"maximoJugadores",
type:"number"
},
{
sqlType:"char",
sqlLength:"1",
title:"Categoria Arbitro Principal",
name:"categoriaArbitroPrincipal",
length:"1",
type:"text"
},
{
sqlType:"decimal",
sqlLength:"18",
title:"Pago Arbitro Principal",
name:"pagoArbitroPrincipal",
type:"float",
validators:[
{
errorMessage:"Please enter a valid cost",
min:0,
precision:2,
type:"floatLimit"
}
]
},
{
sqlType:"char",
sqlLength:"1",
title:"Categoria Arbitro Sustituto",
name:"categoriaArbitroSustituto",
length:"1",
type:"text"
},
{
sqlType:"decimal",
sqlLength:"18",
title:"Pago Arbitro Sustituto",
name:"pagoArbitroSustituto",
type:"float",
validators:[
{
errorMessage:"Please enter a valid cost",
min:0,
precision:2,
type:"floatLimit"
}
]
},
{
sqlType:"char",
sqlLength:"1",
title:"Categoria Jueces Linea",
name:"categoriaJuecesLinea",
length:"1",
type:"text"
},
{
sqlType:"decimal",
sqlLength:"18",
title:"Pago Jueces Linea",
name:"pagoJuecesLinea",
type:"float",
validators:[
{
errorMessage:"Please enter a valid cost",
min:0,
precision:2,
type:"floatLimit"
}
]
},
{
sqlType:"timestamp",
sqlLength:"19",
title:"Fecha de Registro",
name:"fechaRegistro",
type:"date"
},
{
sqlType:"integer",
sqlLength:"10",
title:"Se Viaja ?",
name:"seViaja",
type:"number",
valueMap:{
0:"No",
1:"Si"
}
},
{
sqlType:"integer",
sqlLength:"10",
title:"Combinado",
name:"combinado",
type:"number",
valueMap:{
0:"No",
1:"Si"
}
},
{
sqlType:"integer",
sqlLength:"10",
title:"Torneo",
name:"torneoId",
type:"number",
required:true
}
],
ID:"division"
});
isc.DataSource.create({
serverType:"generic",
fields:[
{
sqlType:"integer",
sqlLength:"10",
title:"Cancha",
primaryKey:true,
hidden:true,
name:"canchaId",
type:"sequence"
},
{
sqlType:"varchar",
sqlLength:"128",
length:"128",
title:"Nombre",
name:"nombre",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
title:"Calle1",
name:"calle1",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
title:"Calle2",
name:"calle2",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
title:"Colonia",
name:"colonia",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"35",
length:"35",
title:"Municipio",
name:"municipio",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"35",
length:"35",
title:"Entidad",
name:"entidad",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
title:"Codigo Postal",
name:"codigoPostal",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
title:"Pais",
name:"pais",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"10",
length:"10",
title:"Telefono1",
name:"telefono1",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"10",
length:"10",
title:"Telefono2",
name:"telefono2",
type:"text"
},
{
sqlType:"integer",
sqlLength:"11",
name:"Largo",
name:"largo",
type:"number"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Ancho",
name:"ancho",
type:"number"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Alumbrado",
name:"alumbrado",
type:"number",
valueMap:{
"0":"No",
"1":"Si"
}
},
{
sqlType:"integer",
sqlLength:"11",
title:"Edad Minima",
name:"edadMinima",
type:"number"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Edad Maxima",
name:"edadMaxima",
type:"number"
},
{
sqlType:"varchar",
sqlLength:"256",
length:"256",
title:"Comentarios",
name:"comentarios",
type:"text"
},
{
sqlType:"integer",
sqlLength:"10",
hidden:true,
title:"EmpresaId",
name:"empresaId",
type:"number"
}
],
ID:"campo"
});
isc.DataSource.create({
serverType:"generic",
fields:[
{
sqlType:"integer",
sqlLength:"10",
title:"Division",
name:"divisionId",
type:"integer",
required:true
},
{
sqlType:"integer",
sqlLength:"10",
title:"Campo",
name:"campoId",
type:"integer",
required:false,
hidden:true
}
],
ID:"divisionCampo"
});
isc.ListGrid.create({
ID:"campoListGrid",
dataSource:campo,
useAllDataSourceFields:true,
fields:[
{
sqlType:"integer",
sqlLength:"10",
primaryKey:true,
hidden:true,
title:"Cancha",
name:"canchaId",
type:"sequence"
},
{
sqlType:"varchar",
sqlLength:"128",
length:"128",
title:"Nombre",
name:"nombre",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
hidden:true,
title:"Calle1",
name:"calle1",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
hidden:true,
title:"Calle2",
name:"calle2",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
hidden:true,
title:"Colonia",
name:"colonia",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"35",
length:"35",
hidden:true,
title:"Municipio",
name:"municipio",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"35",
length:"35",
hidden:true,
title:"Entidad",
name:"entidad",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
hidden:true,
title:"Codigo Postal",
name:"codigoPostal",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
hidden:true,
title:"Pais",
name:"pais",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"10",
length:"10",
hidden:true,
title:"Telefono1",
name:"telefono1",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"10",
length:"10",
hidden:true,
title:"Telefono2",
name:"telefono2",
type:"text"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Largo",
name:"largo",
type:"number"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Ancho",
name:"ancho",
type:"number"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Alumbrado",
name:"alumbrado",
type:"number",
valueMap:{
"0":"No",
"1":"Si"
}
},
{
sqlType:"integer",
sqlLength:"11",
title:"Edad Minima",
name:"edadMinima",
type:"number"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Edad Maxima",
name:"edadMaxima",
type:"number"
},
{
sqlType:"varchar",
sqlLength:"256",
length:"256",
hidden:true,
title:"Comentarios",
name:"comentarios",
type:"text"
},
{
sqlType:"integer",
sqlLength:"10",
hidden:true,
title:"EmpresaId",
name:"empresaId",
type:"number"
}
],
recordClick:"this.updateDetails()",
canEdit:true,
modalEditing:true,
cellChanged:"this.updateDetails()",
alternateRecordStyles:true,
canDragRecordsOut:true,
hoverWidth:200,
hoverHeight:20,
selectionType:"single",
cellContextClick:"return campoMenu.showContextMenu()",
// Function to update details based on selection
updateDetails : function () {
var record = this.getSelectedRecord();
if (record == null) return campoTabSet.clearDetails();
alert("campoTabSet.getSelectedTabNumber() = " + campoTabSet.getSelectedTabNumber());
if (campoTabSet.getSelectedTabNumber() == 0) {
// View tab: show selected record
campoDetailViewer.setData(record)
} else {
alert("ahora si voy a actualizar");
alert("chanchaId = " + record.canchaId);
// Edit tab: edit selected record
campoTabSet.updateTab("editTab", campoVLayout);
campoDynamicForm.editRecord(record);
// divisionCampoListGrid.fetch({"canchaId":record.canchaId});
// divisionCampo.fetch({"canchaId":record.canchaId});
// divisionCampoListGrid.filterData({"canchaId":record.canchaId});
// divisionCampo.fetchData({"canchaId":record.canchaId});
isc.DataSource.get("divisionCampo").fetchData({"canchaId":record.canchaId}, "divisionCampoListGrid.setData(data)");
}
}
});
isc.Menu.create({
ID:"campoMenu",
cellHeight:22,
data:[
{title:"Adiciona Nueva Cancha", icon:"../images/icon_add.png", click:function () {
campoListGrid.selection.deselectAll();
campoTabSet.selectTab(1);
campoListGrid.updateDetails();
}
},
{isSeparator:true},
{title:"Muestra Detalles",
icon:"../images/icon_view.png",
click:"campoTabSet.selectTab(0); campoListGrid.updateDetails()"},
{title:"Edita Cancha",
icon:"../images/icon_edit.png",
click:"campoTabSet.selectTab(1); campoListGrid.updateDetails()"},
{title:"Elimina Cancha",
icon:"../images/icon_delete.png",
click:"campoListGrid.removeSelectedData(); campoTabSet.clearDetails()"}
]
});
isc.DetailViewer.create({
ID:"campoDetailViewer",
dataSource:campo,
width:"100%",
margin:"25",
emptyMessage:"Seleccione una campo para ver su detalle"
});
isc.DynamicForm.create({
ID:"campoDynamicForm",
dataSource:campo,
useAllDataSourceFields:true,
fields:[
{
sqlType:"integer",
sqlLength:"10",
title:"Cancha",
primaryKey:true,
hidden:true,
name:"canchaId",
type:"sequence"
},
{
sqlType:"varchar",
sqlLength:"128",
length:"128",
title:"Nombre",
name:"nombre",
type:"text",
width:535,
colSpan:4
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
title:"Calle1",
name:"calle1",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
title:"Calle2",
name:"calle2",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
title:"Colonia",
name:"colonia",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"35",
length:"35",
title:"Municipio",
name:"municipio",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"35",
length:"35",
title:"Entidad",
name:"entidad",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
title:"Codigo Postal",
name:"codigoPostal",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"30",
length:"30",
title:"Pais",
name:"pais",
type:"text"
},
{
name:"spacer0",
type:"spacer"
},
{
sqlType:"varchar",
sqlLength:"10",
length:"10",
title:"Telefono1",
name:"telefono1",
type:"text"
},
{
sqlType:"varchar",
sqlLength:"10",
length:"10",
title:"Telefono2",
name:"telefono2",
type:"text"
},
{
sqlType:"integer",
sqlLength:"11",
name:"Largo",
name:"largo",
type:"number"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Ancho",
name:"ancho",
type:"number"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Alumbrado",
name:"alumbrado",
type:"number",
valueMap:{
"0":"No",
"1":"Si"
}
},
{
name:"spacer1",
type:"spacer"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Edad Minima",
name:"edadMinima",
type:"number"
},
{
sqlType:"integer",
sqlLength:"11",
title:"Edad Maxima",
name:"edadMaxima",
type:"number"
},
{
sqlType:"varchar",
sqlLength:"256",
length:"256",
title:"Comentarios",
name:"comentarios",
type:"text",
width:535,
colSpan:4
},
{
sqlType:"integer",
sqlLength:"10",
hidden:true,
title:"EmpresaId",
name:"empresaId",
type:"number"
}
],
width:800,
height:200,
numCols:4,
colWidths:[200,200,200,200],
margin:25,
cellPadding:5,
autoFocus:false
});
isc.ListGrid.create({
ID: "divisionCampoListGrid",
width: 300,
height: 200,
layoutAlign:"center",
dataSource: divisionCampo,
canEdit: true,
canRemoveRecords: true,
autoDraw: false,
autoSaveEdits: false,
fields:[
{
sqlType:"integer",
title:"Division",
name:"divisionId",
type:"integer",
editorType:"comboBox",
optionDataSource:"division",
valueField:"divisionId",
displayField:"nombre",
pickListWidth:150
}
]
});
isc.IButton.create({
ID: "addButton",
autoDraw: false,
width: 150,
layoutAlign:"left",
title: "Adiciona Division",
click: "divisionCampoListGrid.startEditingNew()"
});
isc.IButton.create({
ID: "delButton",
autoDraw: false,
width: 150,
layoutAlign:"center",
title: "Elimina Division",
click: function() {
divisionCampoListGrid.removeSelectedData();
var record = campoListGrid.getSelectedRecord();
isc.DataSource.get("divisionCampo").fetchData({"canchaId":record.canchaId}, "divisionCampoListGrid.setData(data)");
}
});
isc.IButton.create({
ID: "saveButton",
autoDraw: false,
width: 150,
layoutAlign:"right",
title: "Almacena Cancha",
click: function() {
isc.RPCManager.startQueue();
campoDynamicForm.saveData();
divisionCampoListGrid.saveAllEdits();
isc.RPCManager.sendQueue();
campoDynamicForm.editNewRecord();
divisionCampoListGrid.setData(null);
}
});
isc.VLayout.create({
ID: "campoVLayout",
membersMargin: 20,
members: [
campoDynamicForm,
divisionCampoListGrid,
isc.HLayout.create(
{
membersMargin:10,
members:[addButton, delButton, saveButton]
}
)
]
});
isc.Label.create({
ID:"campoLabel",
autoDraw: false,
width:"100%",
height:"100%",
align:"center",
contents:"Seleccione una campo a editar"
});
isc.TabSet.create({
ID:"campoTabSet",
tabs:[
{title:"Ver", pane:campoDetailViewer, ID:"viewTab", width:70, icon:"../images/icon_view.png"},
{title:"Editar", pane:campoVLayout, ID:"editTab", width:70, icon:"../images/icon_edit.png"}
],
tabSelected:"campoListGrid.updateDetails()",
// Function to clear out selected items' details
clearDetails : function () {
alert("estoy en clearDetails de TabSet");
var selectedTab = this.getSelectedTabNumber();
if (selectedTab == 0) {
// View tab: show empty message
campoDetailViewer.setData();
} else if (selectedTab == 1) {
// Edit tab: show new record editor, or empty message
// if (categoryTree.getSelectedRecord() != null) {
// alert("entro a categoryTree.getSelectedRecord() != null");
// alert("entro a selectedTab == 1");
this.updateTab("editTab", campoVLayout);
campoDynamicForm.editNewRecord();
divisionCampoListGrid.setData(null);
// } else {
// alert("entro a categoryTree.getSelectedRecord() == null");
// this.updateTab("editTab", campoLabel);
// }
}
}
});
isc.SectionStack.create({
ID:"campoSectionStack",
width:"100%",
height:"100%",
showResizeBar:false,
visibilityMode:"multiple",
animateSections:true,
sections:[
{title:"Canchas Existentes", autoShow:true, items:[campoListGrid]},
{title:"Cancha Detalle", autoShow:true, items:[campoTabSet]}
]
});
oneVLayout.addMember(campoSectionStack);
campoSectionStack.show();
campoListGrid.filterData();
The detail datasource is:
<DataSource
ID="divisionCampo"
serverType="generic">
<fields>
<field sqlType="integer" sqlLength="10" name="divisionId" type="integer"></field>
<field sqlType="integer" sqlLength="10" name="canchaId" type="integer" hidden="true"></field>
</fields>
<operationBindings>
<binding operationType="fetch" serverMethod="fetch">
<serverObject lookupStyle="new" className="dmi.DivisionCampoDMI"/>
</binding>
<operationBinding operationType="add">
<values fieldName="canchaId" value="$responseData.last('campo','add').canchaId" />
<serverObject lookupStyle="new" className="dmi.DivisionCampoDMI"/>
</operationBinding>
<operationBinding operationType="update">
<serverObject lookupStyle="new" className="dmi.DivisionCampoDMI"/>
</operationBinding>
<operationBinding operationType="remove">
<serverObject lookupStyle="new" className="dmi.DivisionCampoDMI"/>
</operationBinding>
</operationBindings>
</DataSource>
The detail DMI is:
// By default, for a DSRequest of type "fetch", a method named "fetch" is invoked. You can
// customize this via the <serverObject> declaration.
public DSResponse fetch(DSRequest dsRequest, HttpSession session) throws Exception {
log.info("procesing DMI fetch operation");
System.out.println("DivisionCampoDMI - fetch");
DivisionCanchaBO divisionCanchaBO = new DivisionCanchaBO();
// Fetch a List of matching SupplyItem Beans from some pre-existing Java object model
// provided by you, represented by "SupplyItemStore" in this example
DivisionCanchaVO divisionCanchaVO = new DivisionCanchaVO();
if(dsRequest.getFieldValue("divisionId") != null) {
Long divisionId = (Long) dsRequest.getFieldValue("divisionId");
divisionCanchaVO.setDivisionId(new Integer(divisionId.intValue()));
} else {
divisionCanchaVO.setDivisionId(null);
}
if(dsRequest.getFieldValue("canchaId") != null) {
Long canchaId = (Long) dsRequest.getFieldValue("canchaId");
divisionCanchaVO.setCanchaId(new Integer(canchaId.intValue()));
} else {
divisionCanchaVO.setCanchaId(null);
}
// Integer empresaId = (Integer) session.getAttribute("empresaId");
List divisionCanchaList = divisionCanchaBO.sel(divisionCanchaVO);
// this implementation shows data paging (returning only ranges of requested records)
long startRow = dsRequest.getStartRow();
long endRow = dsRequest.getEndRow();
long totalRows = divisionCanchaList.size();
DSResponse dsResponse = new DSResponse(dsRequest == null ? (DataSource)null : dsRequest.getDataSource());
dsResponse.setTotalRows(totalRows);
dsResponse.setStartRow(startRow);
endRow = Math.min(endRow, totalRows);
dsResponse.setEndRow(endRow);
// trim the data to the requested range of records. In a real application, the startRow
// and endRow would be passed to the ORM layer or to SQL for maximum efficiency.
List results;
if (totalRows > 0) {
if(endRow < startRow) {
results = divisionCanchaList;
} else {
results = divisionCanchaList.subList((int)dsResponse.getStartRow(), (int)dsResponse.getEndRow());
}
} else {
results = divisionCanchaList;
}
// just return the List of matching beans
dsResponse.setData(results);
return dsResponse;
}
// Declared parameters of the method are automatically provided. For example, if your
// method declares a parameter of type HttpServletRequest, the current HttpServletRequest
// will be passed.
// If you declare a parameter that is a Java Bean, SmartClient will create an instance of
// the bean and apply the DSRequest data to the bean via Java reflection, matching
// DataSource fields to Java setter methods. For example, for the DataSource field
// "itemName", SupplyItem.setItemName() is called.
public DivisionCanchaVO add(DivisionCanchaVO divisionCanchaVO, HttpSession session) throws Exception {
log.info("procesing DMI add operation");
DivisionCanchaBO divisionCanchaBO = new DivisionCanchaBO();
System.out.println("DivisionCampoDMI - add");
// Integer canchaId = (Integer) session.getAttribute("canchaId");
// System.out.println("canchaId --------------------> " + canchaId);
// divisionCanchaVO.setCanchaId(canchaId);
// most ORM systems can store a new Object with a single call like this.
divisionCanchaBO.add(divisionCanchaVO);
// return the record-as-saved so SmartClient can update client-side caches. This
// pattern ensures client-side components receive server-generated fields (such as an
// auto-generated primaryKey value). SmartClient can then update caches in place
// instead of re-fetching data.
return divisionCanchaVO;
}
public DivisionCanchaVO remove(DivisionCanchaVO divisionCanchaVO, HttpSession session) throws Exception {
log.info("procesing DMI remove operation");
DivisionCanchaBO divisionCanchaBO = new DivisionCanchaBO();
System.out.println("DivisionCampoDMI - remove");
divisionCanchaBO.del(divisionCanchaVO);
// on a removal, just return
System.out.println("divisionCanchaVO = " + divisionCanchaVO);
return divisionCanchaVO;
}
Please help me to resolve this problem