Bỏ qua, tới nội dung
Tài liệu APIv1

Nhúng trình soạn thảo

Sự kiện

Bảy sự kiện của O3O.Editor: onReady, onDocumentLoaded, onModified, onSaved, onError, onClose, onLimitReached, từng cái kèm trường và ví dụ.

Trong trang này

Khai báo trong config.events. Mỗi hàm nhận MỘT đối số là đối tượng sự kiện; hàm nào vắng mặt thì bỏ qua. Ngoại lệ ném ra từ hàm của bạn bị bắt và in ra console, không làm hỏng trình soạn thảo.

Sự kiệnKhi nàoĐối tượng
onReadyPhiên đã tạo, iframe đã gắn, khung soạn thảo báo sẵn sàng.{sessionId, mode}
onDocumentLoadedTài liệu đã hiện.{sessionId, mode, loadTimeMs}
onModifiedTrạng thái “có thay đổi chưa lưu” đổi.{modified}
onSavedGate đã nhận một bản lưu mới; đúng một lần cho mỗi số phiên bản.{key, version, url, size, sha256, savedAt}
onErrorBất kỳ lỗi nào.{code, message, detail}
onCloseNgười dùng bấm nút đóng, hoặc trang gọi close().{sessionId, modified}
onLimitReachedXin edit nhưng đã chạm trần; trình soạn thảo vẫn mở ở chế độ chỉ đọc.{limit, current, edition, message, mode}

Thứ tự thông thường: onReadyonDocumentLoaded → (onModified, onSaved)* → onClose.

onReady#

onReady

  • sessionIdstringbắt buộc
    Mã phiên, dạng ses_ + 24 hex.
  • mode"edit" | "view"bắt buộc
    Chế độ thật của phiên (có thể là view nếu đã chạm trần).
JavaScriptonReady
const events = {
  onReady(e) {
    // Khung soạn thảo đã sẵn sàng, tài liệu còn đang nạp
    document.getElementById("status").textContent = "Đang mở tài liệu…";
    console.log(e.sessionId, e.mode);   // "ses_…", "edit" | "view"
  }
};

onDocumentLoaded#

onDocumentLoaded

  • sessionIdstringbắt buộc
    Mã phiên.
  • mode"edit" | "view"bắt buộc
    Chế độ của phiên.
  • loadTimeMsnumberbắt buộc
    Số mili giây từ lúc tạo trình soạn thảo tới lúc tài liệu hiện, đo trên máy người dùng.

Ngay sau sự kiện này api.js áp các tuỳ chọn ui dạng thông điệp (thanh trạng thái, thanh trình đơn).

JavaScriptonDocumentLoaded
const events = {
  onDocumentLoaded(e) {
    document.getElementById("status").textContent = "";
    console.log("mở trong", e.loadTimeMs, "ms, mode =", e.mode);
  }
};

onModified#

onModified

  • modifiedbooleanbắt buộc
    true khi có thay đổi chưa lưu.
JavaScriptonModified
let dirty = false;
const events = {
  onModified(e) {
    dirty = e.modified;
    document.title = (dirty ? "● " : "") + "Hợp đồng";
  }
};
// Nhắc người dùng khi rời trang lúc còn thay đổi chưa lưu
window.addEventListener("beforeunload", (ev) => { if (dirty) ev.preventDefault(); });

onSaved#

onSaved

  • keystringbắt buộc
    document.key của tài liệu.
  • versionintegerbắt buộc
    Số phiên bản mới, tăng dần từ 1.
  • urlstringbắt buộc
    URL tải phiên bản này, có chữ ký, sống trong thời gian giữ (O3O_EMBED_RETAIN_HOURS, mặc định 24 giờ).
  • sizeintegerbắt buộc
    Kích thước tính bằng byte.
  • sha256stringbắt buộc
    Băm SHA-256 dạng hex của tệp.
  • savedAtstringbắt buộc
    Thời điểm lưu, ISO 8601 UTC.
JSONVí dụ đối tượng onSaved
{
  "key": "contract-42-v7",
  "version": 3,
  "url": "http://localhost:8080/o3o/embed/files/doc_9835f61009fc659dfedab8696f2d2665?v=3&exp=1790086400&sig=5f1c…",
  "size": 48890,
  "sha256": "b1946ac92492d2347c6235b4d2611184…",
  "savedAt": "2026-09-21T10:05:00Z"
}
JavaScriptonSaved
const events = {
  onSaved(e) {
    // e.url là URL tải có chữ ký, sống trong thời gian giữ của máy chủ (mặc định 24 giờ)
    console.log(e.key, "v" + e.version, e.size, "bytes", e.sha256, e.savedAt);
    document.getElementById("download").href = e.url;
  }
};

Cách api.js nhận ra bản lưu: khi khung soạn thảo báo lưu thành công, hoặc khi trạng thái “có thay đổi” chuyển từ true sang false, nó hỏi GET /o3o/embed/session/{id} mỗi giây, tối đa 10 lần, cho tới khi version lớn hơn số đã biết, rồi mới phát onSaved.

onError#

onError

  • codestringbắt buộc
    Mã lỗi ổn định, xem bảng mã.
  • messagestringbắt buộc
    Câu tiếng Việt hiện được cho người dùng.
  • detailobjecttuỳ chọnMặc định: {}
    Chi tiết thêm, ví dụ errors của invalid_config.
JSONVí dụ đối tượng onError
{
  "code": "download_failed",
  "message": "Không tải được tài liệu từ địa chỉ đã cho.",
  "detail": {}
}
JavaScriptonError
const events = {
  onError(e) {
    // e.message là câu tiếng Việt, hiện được cho người dùng; e.code dùng để rẽ nhánh
    console.error(e.code, e.message, e.detail);
    if (e.code === "network_error") setTimeout(() => location.reload(), 5000);
  }
};

onClose#

onClose

  • sessionIdstringbắt buộc
    Mã phiên.
  • modifiedbooleanbắt buộc
    Còn thay đổi chưa lưu lúc đóng.
JavaScriptonClose
const events = {
  onClose(e) {
    // iframe đã được gỡ trước khi sự kiện này phát
    if (e.modified) console.warn("đóng khi còn thay đổi chưa lưu");
    location.href = "/documents";
  }
};

onLimitReached#

onLimitReached

  • limitintegerbắt buộc
    Trần kết nối hiệu lực.
  • currentintegerbắt buộc
    Số phiên sửa đang tính.
  • edition"community" | "enterprise"bắt buộc
    Gói đang chạy.
  • messagestringbắt buộc
    Câu tiếng Việt của máy chủ; api.js hiện đúng câu này trên băng thông báo.
  • mode"view"bắt buộc
    Luôn là view.
JSONVí dụ đối tượng onLimitReached
{
  "limit": 50,
  "current": 50,
  "edition": "community",
  "message": "Hệ thống đã đạt giới hạn 50 phiên soạn thảo đồng thời của bản cộng đồng. Tài liệu của bạn vẫn an toàn. Bạn có thể mở ở chế độ chỉ đọc hoặc thử lại sau ít phút.",
  "mode": "view"
}
JavaScriptonLimitReached
const events = {
  onLimitReached(e) {
    // Trình soạn thảo VẪN mở, ở chế độ chỉ đọc (e.mode === "view")
    console.warn(e.limit, e.current, e.edition, e.message);
  }
};

Ví dụ đầy đủ: ghi mọi sự kiện#

HTMLevents.html
<!doctype html>
<meta charset="utf-8">
<div id="o3o-editor" style="height: 70vh"></div>
<pre id="log" style="height: 25vh; overflow: auto; background: #f4f4f4"></pre>
<script src="http://localhost:8080/o3o/api.js"></script>
<script>
  const log = (name) => (e) => {
    document.getElementById("log").textContent += new Date().toISOString() + " " + name + " " + JSON.stringify(e) + "\n";
  };
  new O3O.Editor("o3o-editor", {
    document: { url: "http://localhost:8080/o3o/demo/sample.docx", title: "sample.docx", fileType: "docx", key: "events-demo-1" },
    editor: { mode: "edit", lang: "vi", user: { id: "dev-1", name: "Dev" } },
    ui: { closeButton: true },
    events: {
      onReady: log("onReady"),
      onDocumentLoaded: log("onDocumentLoaded"),
      onModified: log("onModified"),
      onSaved: log("onSaved"),
      onError: log("onError"),
      onClose: log("onClose"),
      onLimitReached: log("onLimitReached")
    }
  });
</script>
Sắp có

Sự kiện cho lưu thành tệp khác và cho lịch sử phiên bản.