简体   繁体   中英

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. What I run my code, the checkbox is always checked regardless of the ajax response. 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. The on- prefix isn't supported by Lit. You're using this.parentNode.removeChild to remove an element on update, but that element is managed by the template. 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' .

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.

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>`;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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