【问题标题】:Vaadin 14 - Error: Detected container element removed from DOMVaadin 14 - 错误:检测到从 DOM 中删除的容器元素
【发布时间】:2021-11-25 13:21:45
【问题描述】:
  • 更新 1: ============
  • 删除"window.ShadyDOM={force:true};" 后,它工作了。但这会导致其他问题;):

https://vaadin.com/forum/thread/17399734/leverage-browser-save-password-feature

@Override
    public void configurePage(InitialPageSettings settings) {
    // TODO Auto-generated method stub
    settings.addMetaTag("mobile-web-app-capable", "yes");
    settings.addMetaTag("apple-mobile-web-app-capable", "yes");
    settings.addMetaTag("apple-mobile-web-app-status-bar-style", "black");

    settings.addInlineWithContents(
        InitialPageSettings.Position.PREPEND, "window.customElements=window.customElements||{};"
            + "window.customElements.forcePolyfill=true;" + "window.ShadyDOM={force:true};",
        InitialPageSettings.WrapMode.JAVASCRIPT);
    }

结束更新。 ============

我正在尝试将 Payal 结帐集成到 Vaadin 14.7(Spring 核心,而不是 Spring Boot)。

这里是 paypal-view.js

import { LitElement, html, css } from "lit-element";

let buttons;
let hasRendered = false;

class PaypalElement extends LitElement {
  static get properties() {
    return {
      mood: {
        type: String,
        noAccessor: false,
        hasChanged(newVal, oldVal) {
          console.log("newVal " + newVal + " oldVal " + oldVal);
        },
      },
    };
  }

  static get styles() {
    return [
      css`
        mood_color {
          color: green;
        }
        #paypal-button {
          size: "responsive";
        }
      `,
    ];
  }

  firstUpdated(_changedProperties) {
    let testFname = this.shadowRoot.getElementById("fname");
    super.firstUpdated(_changedProperties);

    if (buttons && buttons.close && hasRendered) {
      buttons.close();
      hasRendered = false;
    }
    buttons = window.paypal.Buttons({
      // Set up the transaction
      createOrder: function (data, actions) {
        return actions.order.create({
          application_context: {
            brand_name: "Brand name",
            user_action: "PAY_NOW",
            //No shipping for in-tangible merchant
            shipping_preference: "NO_SHIPPING",
            payment_method: {
              payee_preferred: "IMMEDIATE_PAYMENT_REQUIRED", // Pending status transactions will not be allowed if you pass this parameter.
              payer_selected: "PAYPAL",
            },
          },
          purchase_units: [
            {
              soft_descriptor: "CC_STATEMENT_NAME",
              amount: {
                value: "5.00",
              },
            },
          ],
        });
      },

      // Finalize the transaction
      onApprove: function (data, actions) {
        const elementText = document.getElementById("fname");

        return actions.order.capture().then(function (orderData) {
          // Successful capture! For demo purposes:
          console.log(
            "Capture result",
            orderData,
            JSON.stringify(orderData, null, 2)
          );

          let transaction = orderData.purchase_units[0].payments.captures[0];

          // Replace the above to show a success message within this page, e.g.
          // const element = document.getElementById('paypal-button-container');
          // element.innerHTML = '';
          // element.innerHTML = '<h3>Thank you for your payment!</h3>';
          // Or go to another URL:  actions.redirect('thank_you.html');
          document.getElementById("update-paypal-trans").innerHTML =
            "update-paypal-trans = " + transaction.id;

          // trigger lit event
          testFname.value = transaction.id;
          testFname.click();

          document.getElementById("paypalelement").remove();
          //console.log(elementText);
        });
      },

      onError: function (error) {
        console.log("onError", error, JSON.stringify(error, null, 2));
      },

      onCancel: function (data, actions) {
        console.log("onCancel", data, JSON.stringify(data, null, 2));

        document.getElementById("update-paypal-trans").innerHTML =
          "testing 123";

        // update shadow element
        testFname.value = "12345 " + actions;
        // trigger lit event
        testFname.click();
      },
    });

    // load paypal buttons and put them to element id="paypal-button-to-display" which is shadow dom
    buttons
      .render(this.shadowRoot.getElementById("paypal-button-to-display"))
      .then(() => {
        hasRendered = true;
      })
      .catch((err) => {
        console.log(err)
        // not mounted anymore, we can safely ignore the error
        return;
      });
  }

  // outside updates shadow element
  updateShadow() {
    this.shadowRoot.getElementById("test-update-shadow").innerHTML =
      "test update shadow trans";
    this.mood = "nice";
  }

  updateTask(e) {
    console.log("updateTask: " + e);
  }

  updateTaskClick(e) {
    console.log("updateTaskClick: " + e);
    // call back-end
  }

  render() {
    return html`
      Web Components are
      <span class="mood_color"> ${this.mood} and ${this.innerHTML}</span>!
      <input
        type="text"
        id="fname"
        name="fname"
        value="${this.mood}"
        @change=${(e) => this.updateTask(e.target.value)}
        @click="${(e) => this.updateTaskClick(e.target.value)}"
      />
      <div id="paypal-button-to-display"></div>
      <br />
      <div id="test-update-shadow">test-update-shadow-default</div>
      <br />
      <input
        @click="${() => this.updateShadow()}"
        id="myinput"
        type="button"
        value="update shadow button"
      />
    `;
  }

  attributeChangedCallback(name, oldval, newval) {
    super.attributeChangedCallback(name, oldval, newval);
    console.log("attribute change: ", name, newval);
  }

  changeProperties() {
    let randomString = Math.floor(Math.random() * 100).toString();
    this.mood = "myProp " + randomString;
    console.log("randomString change: ", randomString);
  }
}

customElements.define("paypal-element", PaypalElement);

hello-world-view.ts

import { html, LitElement, customElement } from 'lit-element';
import './paypal-view';


import '@vaadin/vaadin-button';
import '@vaadin/vaadin-text-field';

@customElement('hello-world-view')
export class HelloWorldView extends LitElement {

    createRenderRoot() {
        // Do not use a shadow root
        return this;
    }

    constructor() {
        super();
    }
    
    render() {
        return html`
            <vaadin-text-field id="name" label="Your name"></vaadin-text-field>
            <vaadin-button >Say hello</vaadin-button>

            <paypal-elementt mood="great" id="paypalBut">hello customer</paypal-elementt>
          `;
    }

}

hello-world-view.ts

package com.lecompany.iad.view;

import com.lecompany.iad.app.MainView;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.littemplate.LitTemplate;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.template.Id;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouteAlias;

/**
 * A Designer generated component for the stub-tag template.
 *
 * Designer will add and remove fields with @Id mappings but does not overwrite
 * or otherwise change this file.
 */
@PageTitle("Hello World")
@Route(value = "hello", layout = MainView.class)
@Tag("hello-world-view")
@JsModule("./src/view/hello-world-view.ts")
public class HelloWorldView extends LitTemplate {

    @Id
    private TextField name;

//    @Id
//    private Button sayHello;

    public HelloWorldView() {
    
    UI.getCurrent().getPage().addJavaScript("https://www.paypal.com/sdk/js?client-id=AejZZjQsvxS299I2_LSnRkJStp0AsBzScCqbGK1_W6RNJssNR5NVnKYd97dM2kOJnRMF1u1ldLGjOlZ5&currency=USD");
    
//        sayHello.addClickListener(e -> {
//            Notification.show("Hello " + name.getValue());
//        });
    }
}

这是错误:

我在 Spring boot 中测试了上面的代码,然后它工作正常。 但它在正常的弹簧代码中出错。对此有何建议?

Paypal 存在问题。

Paypal reported issue

【问题讨论】:

  • 嗨,下面的答案中有一个指向该错误的链接,但似乎没有直接关系。简而言之,您可能需要使用一个不会在 Shadow DOM 中包装输入元素的组件。查看我的评论 here 以获得一些指示。
  • @SerhiiKulykov 我看不到您对该链接的评论
  • 简而言之,这是因为 Shadow DOM。我们实际上可以选择不将它用于 V14+ 中的输入字段,但它需要编写 HTML。您可以在&lt;vaadin-text-field&gt; 中添加&lt;input slot="input"&gt;。接下来你必须添加这个:createRenderRoot() {return this} - hello-world-view.ts 定义的 TypeScript 类中的该方法将禁用 Shadow DOM。从 Vaadin 22 开始,这是默认方式(文本字段、组合框、日期选择器 - 它们都将在插槽中输入 - 而不是在 Shadow DOM 中)。

标签: vaadin vaadin-flow vaadin14


【解决方案1】:

这是一个 Vaadin 错误并在此处报告:

Vaadin bug

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 2017-11-24
    • 2015-04-20
    • 1970-01-01
    相关资源
    最近更新 更多