简体   繁体   English

使用 Iron-ajax 响应异步更新自定义元素

[英]Asynchronously update a custom element with an iron-ajax response

I am relatively new to lit-element, I took a crack at creating an element that has a checkbox which ideally should get checked based on the response to an ajax call.我对 lit-element 比较陌生,我尝试创建一个具有复选框的元素,理想情况下应该根据对 ajax 调用的响应进行检查。 What I run my code, the checkbox is always checked regardless of the ajax response.我运行我的代码时,无论 ajax 响应如何,都始终选中该复选框。 I also get this error我也收到此错误

Uncaught TypeError: Cannot read property 'shadowRoot' of undefined
    at HTMLElement.<anonymous> (fhir-active-status.js:57)
    at HTMLElement.fire (legacy-element-mixin.js:630)
    at HTMLElement._handleResponse (iron-ajax.js:551)

I think its a life-cycle problem but I can't figure it out.我认为这是一个生命周期问题,但我无法弄清楚。 What am I doing wrong?我究竟做错了什么?

import {LitElement, html} from 'lit-element';
import '@material/mwc-formfield/mwc-formfield.js';
import '@material/mwc-checkbox/mwc-checkbox.js'
import '@polymer/iron-ajax/iron-ajax.js';

class FhirActiveStatus extends LitElement {
    static get properties() {
        return {
            /**activeStatus is used to show active status of person true or false. Use this property to show/hide. Default: true */
            activeStatus: {type:String},
            /**url is used to make AJAX call to FHIR resource. Default: null */
            url: {type:String},
            /**value is used to take the input value of each field*/
            value: {type:Boolean},
        }
    }

    /**default value of properties set in constructor*/
    constructor() {
        super();
        this.activeStatus = 'true';
        this.value = false;
        this.url = "";
    }


   async updated() {
            this.shadowRoot.getElementById('ajax').addEventListener('iron-ajax-response', function (e) {
            var active = this.parentNode.host;
            if (e.detail.response.active) {
                active.shadowRoot.querySelector('.activeState').checked = true;

            }
            else if (!e.detail.response.active) {
                active.shadowRoot.querySelector('.activeState').checked = false;
            }
            else {
                this.parentNode.removeChild(this.parentNode.querySelector('#activeDiv'));
            }
        });
    }

    render() {
        return html`
       <div id="activeDiv">
       ${this.activeStatus !== 'false' ? html`<mwc-formfield class="activeStatus" alignEnd label="ACTIVE STATUS:">
         <mwc-checkbox id="active" checked="${this.value}" class="activeState" on-click="${e => this.value = e.target.value}"></mwc-checkbox>
         </mwc-formfield>` : ''}
         <iron-ajax id="ajax" bubbles auto handle-as="json" url="${this.url}"></iron-ajax>
       </div>
    `;
    }
}

window.customElements.define('fhir-active-status', FhirActiveStatus);

updated can fire when the component isn't connected, so this.parentNode or this.parentNode.host will be empty.当组件未连接时, updated可以触发,因此this.parentNodethis.parentNode.host将为空。 The on- prefix isn't supported by Lit. Lit 不支持on-前缀。 You're using this.parentNode.removeChild to remove an element on update, but that element is managed by the template.您正在使用this.parentNode.removeChild删除更新时的元素,但该元素由模板管理。 You're using querySelector('.activeState') but even if this was on the right shadowRoot it would be error prone because that element will only be in the template when this.activeStatus !== 'false' .您正在使用querySelector('.activeState')但即使它位于正确的shadowRoot上,也容易出错,因为该元素仅在this.activeStatus !== 'false'时才会出现在模板中。

Instead use the built in @event handlers in Lit, and rely on the component lifecycle to do work for you rather than trying to override it.而是使用 Lit 中内置的@event处理程序,并依靠组件生命周期为您工作,而不是试图覆盖它。

async ajaxResponse(e) {
    // Set properties in events, these will automatically queue up a render
    // You don't need to manipulate the DOM here
    this.value = e.detail.response.active;
    this.activeStatus = 'false';
}

render() {
    // This will be called after properties have changed
    // So if @iron-ajax-response calls this.ajaxResponse, 
    // and this.ajaxResponse sets this.activeStatus = 'false'
    // then this will be called again and hide the <mwc-* fields
    return html`
<div id="activeDiv">
    ${this.activeStatus !== 'false' ? html`
    <mwc-formfield class="activeStatus" alignEnd label="ACTIVE STATUS:">
        <mwc-checkbox id="active" checked=${this.value} class="activeState" 
             @click=${e => this.value = e.target.value}></mwc-checkbox>
    </mwc-formfield>` : ''}
         
    <iron-ajax id="ajax" bubbles auto handle-as="json" url=${this.url}
        @iron-ajax-response=${this.ajaxResponse}></iron-ajax>
</div>`;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM