What steps should I take to ensure that an input field triggers a customized query on a JSON API?

I have integrated a Heroku-based Twitter API with my web application, using Angular Material table and other related components.

My goal is to allow users to input a string query and update the displayed results based on that input (with debounce applied).

Here's an example of the API:

https://am-twitter-scrape.herokuapp.com/hashtags/Python?pages_limit=3&wait=0

I want the hashtags value to dynamically change based on user input and reflect updated results. Although I'm following a tutorial at , I am facing difficulties in adapting it to suit my needs.

Currently, my code is neither throwing errors nor functioning correctly. Can someone please provide assistance?

Data service (twitterdata.service.ts)

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Users } from '../models/users.model';

@Injectable()
export class TwitterdataService {

    private myCustomHashtag:string = 'Python';
    private myCustomUser:string = 'Twitter';

    private hashtagsUrl:string = `https://am-twitter-scrape.herokuapp.com/hashtags/${this.myCustomHashtag}?pages_limit=3&wait=0`;
    private usersUrl:string = `http://am-twitter-scrape.herokuapp.com/users/${this.myCustomUser}?pages_limit=3&wait=0`;

    constructor( private http: HttpClient ) { }

    getTweetsByHashtag(): Observable<Users[]> {
        return this.http.get<Users[]>(this.hashtagsUrl);
    }

    getTweetsByUsers(): Observable<Users[]> {
        return this.http.get<Users[]>(this.usersUrl);
    }
}

HTML template for displaying twitter table data (hashtag-tweets-component.html)

<mat-card>

  <div class="search-container" style="direction: rtl;">
    <mat-form-field>
      <mat-icon matPrefix aria-hidden="false" aria-label="Search">search</mat-icon>
      <input matInput #hashtagsSearchInput placeholder="Search by hashtag" [(ngModel)]="myCustomHashtag">
    </mat-form-field>
  </div>

  <div class="spinner-container" *ngIf="dataSource.loading$ | async">
    <mat-spinner></mat-spinner>
  </div>

  <table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
    <ng-container matColumnDef="text">
      <th mat-header-cell *matHeaderCellDef> Tweet </th>
      &td mat-cell *matCellDef="let hashtags"> {{hashtags.text | ellipsis: 50}} </td>
    </ng-container>
   ... // Additional column definitions

<!--Table pagination-->
<mat-paginator
  [length]="length"
  [pageSize]="pageSize"
  [pageSizeOptions]="pageSizeOptions"
  [showFirstLastButtons]="yes">
</mat-paginator>

Typescript file for handling twitter table data (hashtag-tweets-component.ts)

import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';
import { TwitterdataService } from '../services/twitterdata.service';
import { Users } from '../models/users.model';
... // Import statements

@Component({
  selector: 'app-hashtag-tweets',
  templateUrl: './hashtag-tweets.component.html',
  styleUrls: ['./hashtag-tweets.component.sass']
})
export class HashtagTweetsComponent implements OnInit {

    dataSource = new MatTableDataSource<Users>();
    displayedColumns = ['text', 'likes', 'replies', 'retweets', 'hashtags', 'date'];
    ... // Pagination attributes

    @ViewChild('hashtagsSearchInput') hashtagsSearchInput: ElementRef;
    apiResponse:any;
    isSearching:boolean;
    ... // More variables and functions

    convertDate(rawDate: string): string {
        const dateOnly = rawDate.split('-')[1].trim();
        const [day, month, year] = dateOnly.split(' ');
        return `${month} ${day}, ${year}`;
    }

    constructor( private twitterdataService: TwitterdataService ) {
    }
    ... // ngOnInit hook and additional logic

Answer №1

I was able to resolve the issue with the following code. Although I could see the response in the network tab, I was encountering a Cross-Origin Request Blocked error in the console. It seems like in your code, myCustomHashTag is not being updated from the ts file, indicating that arguments are not being passed correctly from the ts class to the service class.

component.html

<div class="row">
  <div class="col-12 text-center">
    <h1>Angular 7 Search using Debounce in RXJS 6.X.X</h1>
    <input type="text" #movieSearchInput class="form-control"
      placeholder="Type any movie name" />

  </div>
</div>

component.ts

import { Component, ViewChild, ElementRef, OnInit } from "@angular/core";
import { of } from "rxjs";
 import {
  debounceTime,
  map,
  distinctUntilChanged,
  filter
} from "rxjs/operators";
import { fromEvent } from 'rxjs';
import { HttpClient, HttpParams } from "@angular/common/http";

import { TwitterTestService } from '../Service/twitter-test.service'

@Component({
  selector: 'app-twitter-test',
  templateUrl: './twitter-test.component.html',
  styleUrls: ['./twitter-test.component.css']
})


export class TwitterTestComponent implements OnInit {

  @ViewChild('movieSearchInput') movieSearchInput: ElementRef;
  apiResponse:any;
  isSearching:boolean;

  constructor(
    private httpClient: HttpClient,
    private twitterTestService:TwitterTestService
  ) {
    this.isSearching = false;
    this.apiResponse = [];
  }

   ngOnInit() {
  fromEvent(this.movieSearchInput.nativeElement, 'keyup').pipe(
    // get value
    map((event: any) => {
      return event.target.value;
    })
    // if character length greater then 2
    ,filter(res => res.length > 2)
    // Time in milliseconds between key events
    ,debounceTime(1000)        
    // If previous query is diffent from current   
    ,distinctUntilChanged()
    // subscription for response
    ).subscribe((text: string) => {
      this.isSearching = true;
      this.twitterTestService.getData(text).subscribe((res)=>{
        console.log("in ts file data is ");
        console.log(res);
      },err=>{
        console.log("error is coming ");
        console.log(err);
      })

    });

service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class TwitterTestService {

  private hasTag:string;
  private baseUrl = 'https://am-twitter-scrape.herokuapp.com/hashtags/';
  constructor(private http: HttpClient) { }


  getData(data) {
     //this.hasTag = data;
     console.log("inside service data url is  ");  
     console.log(this.hasTag);
     return this.http.get(this.baseUrl+data+'?pages_limit=3&wait=0');

 }
}

In addition, if you intend to use templateStringLiterals, it should be contained within a function as they do not update values automatically outside functions. To utilize templateStringLiterals for making an API request, another function needs to be created to return the URL dynamically as shown below.

service.ts

private hasTag:string='';
geturl() {
  return `https://am-twitter-scrape.herokuapp.com/hashtags/${this.hasTag}?pages_limit=3&wait=0`;
}

constructor(private http: HttpClient) { }

getData(data) {
  this.hasTag = data;
  console.log("inside service data url is  ");  
  console.log(this.hasTag);
  console.log("fun is  ");
  let temp = this.geturl();
  console.log("temp is ");
  console.log(temp);
  return this.http.get(temp);

 }

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

Managing $scope within TypeScript code for an AngularJS controller

When using the following code snippet, $scope and $mdDialog are required to be static. declare var module: any; export interface IChangePassword extends ng.IScope { cancel: Function; myname: string; state: string; processRequest: Function; ...

Encountered an issue with the node-mssql error message while attempting a bulk insert: "A premature end-of-message was encountered while reading the current row from the host."

While attempting to utilize the .bulk operation within the node-mssql library in node.js, an error message is being returned: While reading current row from host, a premature end-of-message was encountered--an incoming data stream was interrupted when th ...

Transitioning from es2016 to es2018 or later versions may cause fakeAsync tests to encounter failures

I have been working on upgrading my project and wanted to make sure I was using the latest ECMAScript version. In my tsconfig.spec.json files, I originally had es2016, but I decided to try updating it to 2018 and even experimented with es2022. After chan ...

Customizing hover effects for select field options

I need help customizing the background color of a dropdown menu when hovered over. I attempted to assign a class "page-limit-option" to the option element, but it didn't work. Should I create a new style component instead of using the option? <sele ...

Testing Angular - using observables that return varying values

I'm currently faced with the challenge of testing a component that subscribes to an observable in a service during its ngOnInit lifecycle hook. The component's behavior is expected to change based on the value received from the observable. To sim ...

Change to a dark theme using React hooks in typescript

Hello, I am new to React and English is not my first language, so please excuse any mistakes. I have been trying to enable a dark mode feature on my website. Most examples I have found involve toggling between dark and light modes where you need to specify ...

Selected Angular Radio Button

Back in the good ole days of basic HTML and CSS, I was able to achieve the following: input:checked+label { background-color: #f00; } <div class="col-xs-6"> <input type="radio" id="template-1" name="template" value="template1" checked> ...

Tips on saving a cookie using universal-cookie

I followed a solution on Stack Overflow to set a cookie in my React application. However, the cookie expires with the session. Is there a way I can make this cookie persist beyond the session so it remains even when the browser is closed and reopened? ex ...

Efficient cached selector with computation in @ngrx/store

Here is the structure of my normalized ngrx store: export interface State { carts: EntityState<Cart>; items: EntityState<Item>; } export interface Cart { id: number; maxVolume: number; } export interface Item { id: number ...

Tips for creating a carousel with Angular 9 to showcase numerous items

I've got this code snippet that I'm working on. I want to incorporate a Carousel feature using Angular 9 without relying on any external libraries. Currently, all the data items are appearing in a single row (they are exceeding the specified bor ...

Generating log files in Angular 2 codelogs

As a newcomer to both Angular 2 and typescript, I have a desire to establish a log file in angular 2. Is it feasible to achieve this using angular 2? ...

Watching multiple Angular libraries for changes and serving to a separate application on the go

Currently, I am working on developing three Angular libraries that will be consumed by another main application. My goal is to have live rebuilding for the libraries while my main app imports and runs them simultaneously. This way, I can achieve live reloa ...

Angular 7 and Webpack 4 combine to create a secure environment for CSS encapsulation

I find myself in a challenging situation where I have a hybrid environment consisting of both Angular 1.x and Angular 7 routes. The Angular 1.x routes rely on the older version of Bootstrap (3), while the Angular 7 routes are supposed to utilize Bootstrap ...

Is it considered bad form to utilize nearly identical for loops in two separate instances within Angular 6?

I am working on creating two lists for a roster. The first list will display the current members of this year, while the second list will show if individuals have been excused for this year. After analyzing my code, I realized that I am using two identic ...

Exploring Cypress: Iterating over a collection of elements

I have a small code snippet that retrieves an array of checkboxes or checkbox labels using cy.get in my Angular application. When looping through the array to click on each element and check the checkboxes, it works fine if the array contains only one elem ...

Encountering a problem when attempting to add ngrx to an Angular project

I'm currently in the process of setting up ngrx in my Angular application. After running the command ng add @ngrx/store@latest An error occurred with the following details: npm resolution error report 2022-07-07T20:36:16.089Z While resolving: [em ...

Clearly defining the data types for static dictionary values, while also deducing the precise structure or at least the keys

My goal is to create a static dictionary that is defined as a single object literal. I want to: Specify the type of values explicitly for typechecks and IDE suggestions Still have the ability to infer the exact shape, or at least keys I can achieve the f ...

The module './product-list/product-list.component' could not be located

As a beginner in Angular, I decided to incorporate a top-bar component into my project by following the structure outlined in the app directory. However, I encountered some issues as indicated by the error message that kept popping up. Despite importing ...

Disabling a Text Field based on a Radio Button selection in Angular 4

Below is the form that I am working with: <form #myForm="ngForm" (ngSubmit)="registerUser(form)"> <table class="table borderless"> <tbody> <tr style="width: 100%"> <td > <div cl ...

Updating an array by adding or removing items

I am attempting to create a method for deleting and adding items to an array, but I need easy-to-use delete and add methods since I am unfamiliar with TypeScript. export class NgForComponent implements OnInit { Numbers: number[]; constructor() { ...