Despite successfully making a fetch call and receiving data in the network tab, the DOM is not being updated as expected.
import { html, unsafeCSS, nothing, css } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { AllEtfs } from './queries/all-etfs.js';
import { DsIvsApiBaseComponent } from '../ds-base/ds-base.api.js';
/**
* @tag ds-etf-listing-table
*
*/
@customElement('ds-etf-listing-table')
export class DsEtfListingTable extends DsIvsApiBaseComponent {
static get styles() {
return css`
:host {
display: inline-flex;
align-items: center;
background: blue;
}
`;
}
/**
* @internal
*/
query = AllEtfs.ALL_ETFS_QUERY;
constructor() {
super();
}
protected processResponse(_response): void {
this.componentObject = _response.data;
this.requestUpdate();
}
renderDataGrid() {
if (this.componentObject?.allExchangeTradedFunds) {
const allETFs = this.componentObject.allExchangeTradedFunds;
return html`
${allETFs.forEach((etf) =>
html`
<div class="etf-listing">
<div class="etf-listing__ticker">${etf.ticker}</div>
</div>
`,
)}
`;
}
return html``;
}
updated(changedProperties : Map<string, any>) {
console.log('updated', changedProperties);
console.log('componentObject', this.componentObject);
super.updated(changedProperties);
}
render() {
return this.renderComponent(html`
<section class="content">
<div>${this.renderDataGrid()}</div>
</section>
`);
}
}
import { property, customElement } from 'lit/decorators.js';
import { DsBase } from './ds-base';
/**
* Base class for components that fetch data from the IVS API.
*/
@customElement('ds-ivs-api-base-component')
export class DsIvsApiBaseComponent extends DsBase {
/**
* The fragment used to fetch the data for the component.
*/
@property({
attribute: false,
})
protected query!: string;
/**
* The request query variables.
*/
@property({ attribute: 'data-query-variables', type: String})
protected variables?: string;
constructor() {
super();
}
connectedCallback() {
super.connectedCallback();
this.fetchData().then((response) => {
console.log(" response" + response.data);
this.processResponse(response);
}).catch((error) => {
console.error('Error fetching data:', error);
});
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
protected processResponse(_response) {
// Component must override
console.warn('processResponse must be overridden');
}
protected getQueryVariables(): Record<string, unknown> {
try {
return JSON.parse(this.variables || '{}');
} catch (e) {
console.warn('Invalid or No query variables', e);
return {};
}
}
protected getQuery(): string {
return this.query;
}
/** write code to make a fetch request to the IVS API using the getApiUrl, getQuery, and getQueryVariables methods. **/
protected async fetchData(): Promise<any> {
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-TRP-Requested-With': 'XMLHttpRequest',
'apikey': 'xxxxxx'
},
body: JSON.stringify({
query: this.getQuery(),
variables: this.getQueryVariables(),
}),
});
return response.json();
}
}
import { LitElement, html, unsafeCSS } from 'lit';
import { property, customElement, state } from 'lit/decorators.js';
import { Constants } from './ds-base.constants';
type TTrackingHTMLElement = HTMLElement &
Record<string, (originalEvent: Event) => void>;
/**
* Base class for components that includes Beacon
* @tag ds-base
*/
@customElement(Constants.TAG_NAME)
export class DsBase extends mixin(LitElement, ComponentLoaderMixin) {
/**
* @internal
*/
static styles = [unsafeCSS(`/// styles imported via <link>\n`)];
/**
* @internal
*/
@state()
tagName = '';
/**
* The current version of the pop component, used for version specific scoping
* @internal
*/
@property({ attribute: Constants.DS_VERSION, reflect: true })
version = Constants.VERSION;
/**
* The current version of the pop component, used for version specific scoping
* @internal
*/
@property({ attribute: Constants.DS_VERSION, reflect: true })
stylesheetUrl = Constants.VERSION;
@property({
type: Object,
attribute: false,
})
componentObject?: unknown;
constructor() {
super();
}
connectedCallback() {
super.connectedCallback();
DigitalSharedAnalytics.unsetHostEventHandlerForAnalytics(
this as unknown as TTrackingHTMLElement,
);
DigitalSharedAnalytics.setHostEventHandlerForAnalytics(
this as unknown as TTrackingHTMLElement,
Constants.DS_VERSION,
this.version,
);
}
/**
* If the component is disconnected from the DOM, remove the analytics event listeners.
*/
disconnectedCallback() {
DigitalSharedAnalytics.unsetHostEventHandlerForAnalytics(
this as unknown as TTrackingHTMLElement,
);
super.disconnectedCallback();
}
/*
* This method is called from the Component Loader Mixin once any Defer conditions are met.
* No need to override this method when extending the Base Component.
* Wrapper to be used inside of the `render()` method
* @example
* render() {
* return this.renderComponent(html`<p>meow</p>`)
* }
*/
protected renderComponent(
content: unknown,
classes = 'beacon-theme-modern-outlook',
) {
return !this.initialized
? html`<!--- Not Initialized --->`
: html`
<div data-base-container class="b-reset ${classes}">${content}</div>
`;
}
render() {
return this.renderComponent(html`<!--- Base Render Content --->`);
}
}
My setup consists of ds-base.ts, ds-base.api.ts, and etf-listing-table.ts. I have placed the fetch call within connectedCallBack, with the processResponse method setting componentObject. Despite debugging the code and confirming its execution, the renderDataGrid HTML does not appear on the page.
If you happen to know why the HTML is not rendering despite the code functioning correctly, please let me know.