Xpages XPage repeat控件中未触发onChange事件
我有一个大的“订单”XPage,显示99行,每行有3个文本输入框。 为了捕获更改,我在每个输入框的“onchange”事件中调用了SSJS函数。 调用只发送产品ID、更改类型(哪列)和数量。 然后,SSJS函数将这些更改保存在sessionScope变量(java.util.HashMap)中。 没有与更改关联的刷新 当用户单击“提交”按钮时,将对更改进行整体处理。 这是另一个SSJS函数,它只将所有更改写入后端Domino数据库 这一切似乎都很好,已经做了几年了。 然而,我的用户似乎对应用程序变得太高效了,而且打字速度比它能跟上的还要快 我的调试代码将每个更改写入服务器的控制台,并且我可以看到,如果用户快速连续地进行更改(它们只是在输入框之间切换),某些更改将被忽略。这几乎就好像服务器忙于处理之前的更改,跳过一个而不继续进行另一个更改。有时,整个更改块都会丢失,然后应用程序会在可能的时候恢复 我是否使用了错误的技术来捕获更改?我是否可以确保应用程序每次都启动onchange事件 我已经用IE8/9和FF24测试过了。 我看过其他类似的帖子,它们建议使用“onkeyup”事件来代替。我认为这在我的情况下不起作用,因为用户可能订购两位数的数量 如有任何/所有建议,将不胜感激 特里, 您需要重新审视体系结构。如果更新是在提交时处理的,那么为什么还要麻烦将它们单独发送到服务器呢?正如Tim很好地指出的那样。我要做的是:Xpages XPage repeat控件中未触发onChange事件,xpages,onchange,serverside-javascript,Xpages,Onchange,Serverside Javascript,我有一个大的“订单”XPage,显示99行,每行有3个文本输入框。 为了捕获更改,我在每个输入框的“onchange”事件中调用了SSJS函数。 调用只发送产品ID、更改类型(哪列)和数量。 然后,SSJS函数将这些更改保存在sessionScope变量(java.util.HashMap)中。 没有与更改关联的刷新 当用户单击“提交”按钮时,将对更改进行整体处理。 这是另一个SSJS函数,它只将所有更改写入后端Domino数据库 这一切似乎都很好,已经做了几年了。 然而,我的用户似乎对应用程序
- 创建2个Java类:一个“Order”一个“LineItem”
- 让Order类实现映射接口映射
- 将Order类用于repeat控件(它将为您提供每个行项目的键作为repeat变量)
- 将repeat to Order[RepeatKey].fieldName中的字段绑定到
- 在对象数据源中使用顺序
- 在Order类中实现save方法,并在对象数据源的save方法中调用它
public class LineItem {
private String unid;
private String partno;
private int quantity;
private long unitprice;
/**
* Constructor for new items
*/
public LineItem() {
this.unid = null;
}
/**
* Constructor for existing items
*/
public LineItem(Document doc) {
this.unid = doc.getUniversalId();
// more here
}
/**
* @return the unid
*/
public String getUnid() {
return this.unid;
}
/**
* @return the partno
*/
public String getPartno() {
return this.partno;
}
/**
* @param partno the partno to set
*/
public void setPartno(String partno) {
this.partno = partno;
}
/**
* @return the quantity
*/
public int getQuantity() {
return this.quantity;
}
/**
* @param quantity the quantity to set
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}
/**
* @return the unitprice
*/
public long getUnitprice() {
return this.unitprice;
}
/**
* @param unitprice the unitprice to set
*/
public void setUnitprice(long unitprice) {
this.unitprice = unitprice;
}
public void save(Database db) {
Document doc = null;
if (this.unid == null) {
doc = db.createDocument();
doc.replaceItem("Form", "LineItem");
}
doc.replaceItem("PartNo", this.partno);
// More here
doc.save();
}
}
对于订单-假定您从文档集合加载
public class Order implements Map<String, LineItem> {
// You might want to have a stack here to keep order
private final Map<String, LineItem> backingMap = new LinkedHashMap<String, LineItem>();
private final Set<String> deletedItemKeys = new HashSet<String>();
// The key we use for new items when unid is null
private int lastNewItemNumber = 0;
@Override
public int size() {
return this.backingMap.size();
}
@Override
public boolean isEmpty() {
return this.backingMap.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return this.backingMap.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return this.backingMap.containsValue(value);
}
@Override
public LineItem get(Object key) {
return this.backingMap.get(key);
}
@Override
public LineItem put(String key, LineItem value) {
// Here it gets a little special
// We need to prevent null keys
if (key == null) {
key = String.valueOf(this.lastNewItemNumber);
lastNewItemNumber++;
}
this.deletedItemKeys.remove(key);
return this.backingMap.put(key, value);
}
@Override
public LineItem remove(Object key) {
this.deletedItemKeys.add(key.toString());
return this.backingMap.remove(key);
}
@Override
public void putAll(Map<? extends String, ? extends LineItem> m) {
for (Map.Entry<? extends String, ? extends LineItem> me : m.entrySet()) {
this.put(me.getKey(), me.getValue());
}
}
@Override
public void clear() {
this.deletedItemKeys.addAll(this.backingMap.keySet());
this.backingMap.clear();
}
@Override
public Set<String> keySet() {
return this.backingMap.keySet();
}
@Override
public Collection<LineItem> values() {
return this.backingMap.values();
}
@Override
public Set<java.util.Map.Entry<String, LineItem>> entrySet() {
return this.backingMap.entrySet();
}
public void load(NotesDocumentCollection dc) throws NotesException {
Document doc = dc.getFirstDocument();
Document nextDoc;
while (doc != null) {
nextDoc = dc.getNextDocument(doc);
LineItem li = new LineItem(doc);
this.put(doc.getUniversalId(), li);
doc.recycle();
doc = nextDoc;
}
doc.recyle();
}
public void save(Database db) {
for (LineItem item : this.backingMap.values()) {
item.save(db);
}
// Now kill the left overs - needs error handling
for (String morituri : this.deletedItemKeys) {
Document delDoc = db.getDocumentByUnid(morituri);
if (delDoc != null) {
delDoc.remove(true);
}
}
}
}
公共类顺序实现映射{
//你可能想在这里堆一堆来维持秩序
private final Map backingMap=新建LinkedHashMap();
私有最终集deletedItemKeys=新HashSet();
//unid为null时用于新项的键
private int lastNewItemNumber=0;
@凌驾
公共整数大小(){
返回此.backingMap.size();
}
@凌驾
公共布尔值为空(){
返回此.backingMap.isEmpty();
}
@凌驾
公共布尔containsKey(对象键){
返回此.backingMap.containsKey(键);
}
@凌驾
公共布尔包含值(对象值){
返回此.backingMap.containsValue(值);
}
@凌驾
公共行项目获取(对象键){
返回此.backingMap.get(键);
}
@凌驾
公共行项目放置(字符串键、行项目值){
//这里有点特别
//我们需要防止空键
if(key==null){
key=String.valueOf(this.lastNewItemNumber);
lastNewItemNumber++;
}
此.deletedItemKeys.remove(键);
返回this.backingMap.put(键,值);
}
@凌驾
删除公用行项目(对象键){
this.deletedetemkeys.add(key.toString());
返回此.backingMap.remove(键);
}
@凌驾
公共空间putAll(地图Terry,
你需要重新审视体系结构。如果更新是在提交时处理的,为什么还要麻烦将它们单独发送到服务器上呢?正如Tim很好地指出的那样。我会做什么:
- 创建2个Java类:一个“Order”一个“LineItem”
- 让Order类实现映射接口映射
- 将Order类用于repeat控件(它将为您提供每个行项目的键作为repeat变量)
- 将repeat to Order[RepeatKey].fieldName中的字段绑定到
- 在对象数据源中使用顺序
- 在Order类中实现save方法,并在对象数据源的save方法中调用它
非常粗略的大纲,如果你需要我详细说明,请告诉我。Java集合框架是你的朋友
这比看起来容易:
public class LineItem {
private String unid;
private String partno;
private int quantity;
private long unitprice;
/**
* Constructor for new items
*/
public LineItem() {
this.unid = null;
}
/**
* Constructor for existing items
*/
public LineItem(Document doc) {
this.unid = doc.getUniversalId();
// more here
}
/**
* @return the unid
*/
public String getUnid() {
return this.unid;
}
/**
* @return the partno
*/
public String getPartno() {
return this.partno;
}
/**
* @param partno the partno to set
*/
public void setPartno(String partno) {
this.partno = partno;
}
/**
* @return the quantity
*/
public int getQuantity() {
return this.quantity;
}
/**
* @param quantity the quantity to set
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}
/**
* @return the unitprice
*/
public long getUnitprice() {
return this.unitprice;
}
/**
* @param unitprice the unitprice to set
*/
public void setUnitprice(long unitprice) {
this.unitprice = unitprice;
}
public void save(Database db) {
Document doc = null;
if (this.unid == null) {
doc = db.createDocument();
doc.replaceItem("Form", "LineItem");
}
doc.replaceItem("PartNo", this.partno);
// More here
doc.save();
}
}
对于订单-假定您从文档集合加载
public class Order implements Map<String, LineItem> {
// You might want to have a stack here to keep order
private final Map<String, LineItem> backingMap = new LinkedHashMap<String, LineItem>();
private final Set<String> deletedItemKeys = new HashSet<String>();
// The key we use for new items when unid is null
private int lastNewItemNumber = 0;
@Override
public int size() {
return this.backingMap.size();
}
@Override
public boolean isEmpty() {
return this.backingMap.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return this.backingMap.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return this.backingMap.containsValue(value);
}
@Override
public LineItem get(Object key) {
return this.backingMap.get(key);
}
@Override
public LineItem put(String key, LineItem value) {
// Here it gets a little special
// We need to prevent null keys
if (key == null) {
key = String.valueOf(this.lastNewItemNumber);
lastNewItemNumber++;
}
this.deletedItemKeys.remove(key);
return this.backingMap.put(key, value);
}
@Override
public LineItem remove(Object key) {
this.deletedItemKeys.add(key.toString());
return this.backingMap.remove(key);
}
@Override
public void putAll(Map<? extends String, ? extends LineItem> m) {
for (Map.Entry<? extends String, ? extends LineItem> me : m.entrySet()) {
this.put(me.getKey(), me.getValue());
}
}
@Override
public void clear() {
this.deletedItemKeys.addAll(this.backingMap.keySet());
this.backingMap.clear();
}
@Override
public Set<String> keySet() {
return this.backingMap.keySet();
}
@Override
public Collection<LineItem> values() {
return this.backingMap.values();
}
@Override
public Set<java.util.Map.Entry<String, LineItem>> entrySet() {
return this.backingMap.entrySet();
}
public void load(NotesDocumentCollection dc) throws NotesException {
Document doc = dc.getFirstDocument();
Document nextDoc;
while (doc != null) {
nextDoc = dc.getNextDocument(doc);
LineItem li = new LineItem(doc);
this.put(doc.getUniversalId(), li);
doc.recycle();
doc = nextDoc;
}
doc.recyle();
}
public void save(Database db) {
for (LineItem item : this.backingMap.values()) {
item.save(db);
}
// Now kill the left overs - needs error handling
for (String morituri : this.deletedItemKeys) {
Document delDoc = db.getDocumentByUnid(morituri);
if (delDoc != null) {
delDoc.remove(true);
}
}
}
}
公共类顺序实现映射{
//你可能想在这里堆一堆来维持秩序
private final Map backingMap=新建LinkedHashMap();
私有最终集deletedItemKeys=新HashSet();
//unid为null时用于新项的键
private int lastNewItemNumber=0;
@凌驾
公共整数大小(){
返回此.backingMap.size();
}
@凌驾
公共布尔值为空(){
返回此.backingMap.isEmpty();
}
@凌驾
公共布尔containsKey(对象键){
返回此.backingMap.containsKey(键);
}
@凌驾
公共布尔包含值(对象值){
返回此.backingMap.containsValue(值);
}
@凌驾
公共行项目获取(对象键){
返回此.backingMap.get(键);
}
@凌驾
公共行项目放置(字符串键、行项目值){
//这里有点特别
//我们需要防止空键
if(key==null){
key=String.valueOf(this.lastNewItemNumber);
lastNewItemNumber++;
}
此.deletedItemKeys.remove(键);
返回this.backingMap.put(键,值);
}
@凌驾
删除公用行项目(对象键){
this.deletedetemkeys.add(key.toString());
返回此.backingMap.remove(键);
}
@凌驾