Retrieve data, make a request, display changes, refresh and enhance -

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.

Answer №1

Within the renderDataGrid method, there is a usage of forEach to iterate over an array without returning any values. It would be more appropriate to switch to using the map operator instead for this scenario.

  renderDataGrid() {
       if (this.componentObject?.allExchangeTradedFunds) {
          const allETFs = this.componentObject.allExchangeTradedFunds;
          return html`
            ${allETFs.map((etf) =>
              html`
                <div class="etf-listing">
                  <div class="etf-listing__ticker">${etf.ticker}</div>
                </div>
              `,
            )}
          `;
        }
    
        return html``;
    }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The AngularJS controller is triggered twice

I'm facing an issue where a controller seems to be executing twice, even though I cannot find any duplicates in my files. Running a case sensitive search through my code only reveals one instance of the controller in route configuration and the actual ...

Implementing a Bootstrap 4 modal in Webpack 2

Utilizing only the bootstrap modal functionality, I manually included the required libs (modal.js & util.js) in the vendor section of webpack.config.js If I directly add the vendor.js file, everything works fine. However, since it is bundled, I prefer ...

Encountering errors while attempting to share files in a system built with Node.js, Express,

This snippet shows my Node.js code for connecting to a database using Mongoose const mongoose = require('mongoose'); function connectDB() { // Establishing Database connection mongoose.connect(process see your Naughty's you're sure ...

Is there a way to stop observing an Observable or Subject after its first emission while setting up the observer?

Currently, I am in the process of implementing dialogs using Angular 9 and I encountered a scenario where I need to unsubscribe from a Subject after its first emission. Initially, my approach was to use the take(1) or first() operators to transform the Su ...

Tips for sending a JSON array from a controller to JavaScript using AJAX in a view file

I've been struggling to send an array of Document objects from a method (let's say it's in a controller) to the JavaScript function where the method is being called (in a view). Oddly enough, the method refuses to pass the array - it only wo ...

Is it a good idea to steer clear of including OAuth tokens in the

Utilizing my OAuth2 token in my API program is essential. However, I am also keen on sharing my code through GitHub. How can I securely use my confidential token without including it directly in my source code? ...

Add a new MySQL record using PHP and AJAX

Attempting to add a new entry into my database using AJAX for the first time. Below is the code I am currently working with... Form <form> <input type="text" id="salary" name="salary"> <input type="button" onclick="insertSalary( ...

Update the content of an image in a Div without altering its filename

My application's backend updates an image file and sends the filename back to the front-end: $('#giffinal').html(ResponseGo); However, when I update the image again through the backend, the code in the div on the front-end does not change. ...

Can anyone assist me in developing a code that logs either YES or NO in Javascript?

Looking for a code that can log either YES or NO in Javascript. Can anyone help me out with this? console.log(Math.random() >= 0.5 ? 'YES' : 'NO'); I've attempted using console.log(Math.round(Math.random)) but it doesn't ...

Is fnPageChange malfunctioning due to a delay issue in JavaScript? Possible sequence error?

I have encountered an unusual problem that seems to be affecting several websites I manage using datatables. Whenever I try to use the fnPageChange function, it does not work unless there is a setTimeout workaround like this; setTimeout(function() { oTab ...

Identify the presence of <br /> within a string and envelop the text with <p>

Can a string in JavaScript be parsed to wrap text blocks separated by 2 <br /> tags with opening and closing <p> tags instead of paragraph breaks? Here is an example text: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec od ...

I encountered an error while working with Node.js where it stated that `readFileSync` is

In my current web app project, I am utilizing Angular 2, typescript, Node.js, and Visual Studio. The task at hand is to access a file stored in the wwwroot folder. To accomplish this, I have devised the following class: ///<reference path="../../node_m ...

Exploring error handling in onApplicationBootstrap() within NestJS

I have a TowerService method marked with @Injectable that is running in the onApplicationBootstrap() lifecycle hook. @Injectable() export class TasksService implements OnApplicationBootstrap { private readonly logger = new Logger(TasksService.name) co ...

React-onclickoutside does not function properly within an iframe

I have developed a custom drop-down list using reactjs. I utilized react-onclickoutside to recognize clicks outside the list and close it. While this method works effectively, it does not respond to clicks within an iframe. import onClickOutside from &apo ...

Functionality is successful in one browser, yet encounters issues in another

Here is a straightforward script that allows you to choose a State which then determines the Region, and when clicked it directs you to the corresponding website. This script functions perfectly in IE. You can find the code at I've made numerous at ...

Issue encountered while trying to install Yeoman on Yosemite

I've been attempting for days to install Yeoman on my OS X, but I'm having no luck =/ Every time I try to install it, I encounter this error: Mac-Pro:~ pauloricardo$ sudo npm i -g yo Password: > <a href="/cdn-cgi/l/email-protection" clas ...

Is there a way to verify if a button has been clicked in node.js?

I need to determine if a button has been clicked and then display a new HTML file. I am currently using the express.js app.get method to open my HTML files. Can someone please explain how I can direct a button click to open a new HTML file in the same br ...

Uploading a file with HTML file input leads to the destruction of the parent component

Consider a straightforward angular component structured like this: import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; @Component({ selector: 'app-upload', templateUrl: './upload.component.html', ...

Retrieving player statistics through the NHL API

I've been struggling for the past two weeks to figure out how to fetch player stats from this NHL API when a player is clicked. You can see an example of what I'm trying to achieve by clicking on this player stats link. Any assistance with this w ...

Tips for creating a responsive iframe without relying on aspect ratio assumptions

Is there a way to create a responsive iframe without relying on a fixed aspect ratio? The width and height of the content are unknown until rendering. Keep in mind, using Javascript is an option. For instance: <div id="iframe-container"> <i ...