PowerPoint Content加载项-与`<select />`元素交互时,不会触发`saveAsync`回调

问题描述

上下文

Office JavaScript API定义了saveAsync method,以将设置持久保存到文档中(例如PowerPoint演示文稿)。

这是一个异步方法,一旦设置被持久保存,就会触发回调。在某些情况下,永远不会调用该回调。 This repo显示了在HTML中存在选择器时从不调用回调的情况。

系统信息

此问题的转载与

  • 具有开发人员许可的64位Microsoft PowerPoint for Office 365 MSO(16.0.12527.21096)
  • Windows 10 Pro,版本2004,操作系统内部版本19041.572

如何重现问题

使用the repo中的代码,执行以下操作:

  1. 打开PowerPoint
  2. 创建一个新的演示文稿
  3. 插入“ [dev]计数器”加载项
  4. 加载后,单击“增量”。状态应更新,日志应显示“ ...”
  5. 单击<select />元素并更改其值。
  6. 点击“增量”
  • 预期:调用saveAsync回调(如日志中所示)
  • 实际上:从未调用saveAsync回调(它不会显示在日志中)。

您还可以找到显示问题的video here

注意:

  • <select />除了重现此错误外,没有其他目的。代码中未使用它。
  • 即使未调用saveAsync回调,该状态仍保持不变。可以通过保存演示文稿并再次打开它来验证这一点。

回购中的相关文件

manifest.xml

<?xml version="1.0" encoding="UTF-8"?>
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0"
  xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="ContentApp">
  <Id>735ee73e-fff2-45ee-be66-c0058ffef552</Id>
  <Version>1.0.0.0</Version>
  <ProviderName>Selector</ProviderName>
  <DefaultLocale>en-US</DefaultLocale>
  <AllowSnapshot>false</AllowSnapshot>
  <DisplayName DefaultValue="[dev] Counter" />
  <AppDomains>
    <AppDomain>localhost:5500</AppDomain>
  </AppDomains>
  <Hosts>
    <Host Name="Presentation" />
  </Hosts>
  <DefaultSettings>
    <SourceLocation DefaultValue="http://localhost:5500/index.html" />
    <RequestedWidth>500</RequestedWidth>
    <RequestedHeight>500</RequestedHeight>
  </DefaultSettings>
  <Permissions>ReadWriteDocument</Permissions>
</OfficeApp>

index.html

<!DOCTYPE html>
<html>
  <head>
    <script
      type="text/javascript"
      src="https://appsforoffice.microsoft.com/lib/1/hosted/Office.js"
    ></script>
    <link href="./style.css" rel="stylesheet" />
    <script src="./index.js"></script>
  </head>
  <body>
    <div class="wrapper">
      <div class="half">
        <p>Current state: <span id="state"></span></p>
        <button id="increment-button">Increment</button>
        <select>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
      </div>
      <div class="half">
        <h1 class="logs-title">Logs</h1>
        <ul class="logs" id="logs"></ul>
      </div>
    </div>
  </body>
</html>

index.js

/**
 * Logs a message in the logs "list".
 * @param {String} message - Message to log
 */
function logMessage(message) {
  const pElement = document.createElement('li')
  pElement.textContent = message

  document.querySelector('#logs').appendChild(pElement)
}

/**
 * Returns the value of settings saved in the document settings.
 * @param {String} name - Name of the setting
 */
function getState(name) {
  return Office.context.document.settings.get(name)
}

/**
 * Sets the value of a setting in the document settings.
 * @param {String} name - Name of the setting
 * @param {String} val - Value for this setting
 */
function setState(name,val) {
  logMessage(`Calling \`setState\` with ${name} and ${val}`)

  return Office.context.document.settings.set(name,val)
}

/**
 * Saves the document settings so the changes are persisted in the
 * document.
 */
function saveState() {
  logMessage('Calling `saveState`')

  return Office.context.document.settings.saveAsync((asyncResult) => {
    logMessage(
      `\`saveAsync\` callback called with ${JSON.stringify(asyncResult)}`
    )

    const newState = getState('state')
    logMessage(`newState ${newState}`)
    document.querySelector('#state').textContent = newState
  })
}

/**
 * Increments the counter by 1.
 */
function incrementState() {
  const currentState = getState('state')

  const newState = typeof currentState === 'number' ? currentState + 1 : 0

  setState('state',newState)

  saveState()
}

Office.onReady().then(() => {
  document
    .querySelector('#increment-button')
    .addEventListener('click',incrementState)

  const initialState = getState('state')

  // Initialise the state with the value in the document settings if
  // present.
  if (typeof initialState === 'number') {
    document.querySelector('#state').textContent = initialState
    logMessage(`initialState ${initialState}`)
  }
})

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)