【问题标题】:onChange events not firing in an XPage repeat control在 XPage 重复控件中未触发 onChange 事件
【发布时间】:2013-11-18 11:15:46
【问题描述】:

我有一个大的“订单”XPage,它显示 99 行,每行有 3 个文本输入框。 为了捕捉变化,我在每个输入框的“onchange”事件中调用了一个 SSJS 函数。 该调用仅发送产品 ID、更改类型(哪一列)和数量。 然后,SSJS 函数将这些更改保存在 sessionScope 变量 (java.util.HashMap) 中。 没有与更改关联的刷新。

当用户单击“提交”按钮时,更改会被整体处理。 这是另一个 SSJS 函数,它简单地将所有更改写入后端 Domino 数据库。

这一切似乎都运行良好,并且已经完成了几年。 但是,我的用户似乎在使用该应用程序时变得过于高效,并且打字速度快得跟不上。

我的调试代码将每个更改写入服务器的控制台,如果用户快速连续地进行更改(他们只是在输入框之间切换),我可以看到某些更改被简单地忽略了。就好像服务器忙于处理先前的更改并跳过一个移动到另一个。有时,整个更改块都会丢失,然后应用程序会在可能的情况下重新启动。

我是否使用了错误的技术来捕获更改?我可以做些什么来确保应用程序每次都启动 onchange 事件?

我已经使用 IE8/9 和 FF24 对此进行了测试。 我查看了其他建议使用“onkeyup”事件的帖子。我认为这对我来说行不通,因为用户可能会订购两位数的数量。

任何/所有建议将不胜感激!

【问题讨论】:

  • 一次只能运行一个事件,因此如果在前一个事件仍处于挂起状态时触发了一个事件,它将自动阻止新事件。既然这些数据在“提交”之前什么都不会发生,为什么要为每个组件触发一个单独的更改事件?
  • 感谢蒂姆的回复!抱歉,我错过了解释的关键部分......我需要存储用户在提交订单之前所做的更改,因为订单表单上有多个页面(不仅仅是最初的 99 行)。通过将每个单独的更改存储在 sessionScope 变量中,我可以在用户单击提交按钮时将它们一起提交。
  • 对不起,再多一点来支持我在提交时“批处理”所有更改的理由 - 业务逻辑规定所有更改都必须一起处理。购买规则逻辑(多项目购买折扣、必须一起购买的项目等)包含在与 Notes 客户端共享的 LotusScript 库中,并且该库依赖于提交的更改的完整批次。
  • 其实我并不是要说服你放弃批处理;相反,放弃个别处理。您现有的事件将信息放在会话范围内......相反,将整个界面(或至少重复)绑定到范围内的对象,当单击“提交”时,无论如何,您的范围都会自动更新涉及许多行。这基本上就是斯蒂芬的回答所说明的。
  • 谢谢蒂姆-我明白了。我已经使用了 Stephan 的 cmets/code,并开始学习/开发托管 bean 解决方案。非常感谢您抽出宝贵时间进行解释,并期待在奥兰多为大家买一杯饮料!

标签: xpages onchange serverside-javascript


【解决方案1】:

特里, 你需要重新审视架构。如果更新是在提交时处理的,为什么还要费心将它们单独发送到服务器 - 正如 Tim 很好地指出的那样。我会做什么:

  • 创建 2 个 Java 类:一个“Order”一个“LineItem”
  • 让Order类实现Map接口Map
  • 使用 Order 类进行重复控制(它将为您提供每个 LineItem 的键作为重复变量)
  • 将repeat里面的字段绑定到Order[RepeatKey].fieldName
  • 在对象数据源中使用 Order
  • 在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);
        }
    }       
}
}

【讨论】:

  • 谢谢斯蒂芬!我知道你会带回一个让我意想不到的解决方案。该死的,我希望我更了解Java!我会研究一下(你早在 2011 年 2 月就建议过这种方法,而我的 Java 技能还不够先进!),但可能需要找比我知识渊博的人来提供帮助。
  • 特里 - 这比听起来容易。看看上面的示例类
  • 你是传奇斯蒂芬!今天晚上我会试一试,让你知道我是多么公平。提醒我在奥兰多给你买几杯饮料!你去吗?一定要带上“黄色家伙”(垫子)!!
  • 你可以的,特里!祝你好运。我们随时为您提供帮助,以防万一:-)
  • 一切看起来都很好,只有一个例外。我正在使用 NotesViewEntries 收集详细信息,以确保按照我希望它们在重复控件中显示的顺序收集它们。然而,当它们显示时,它们的顺序与我预期的完全不同。我注意到你的评论斯蒂芬:“你可能想在这里有一个堆栈来保持秩序”。您能否详细说明这一点,以便我可以尝试确保 entrySet 顺序代表获取详细信息的顺序?再次感谢您迄今为止的所有帮助 - 我可能会按时完成这件事!
猜你喜欢
  • 2017-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多