Can you set up a mechanism to receive notifications for changes in an array variable in Angular?

I'm exploring methods to delay an HTTP request until the user stops interacting. I am considering using the debounceTime() operator from RxJs, but I need this to be triggered by changes in an array that I have defined.

Here is the scenario:

export class KeywordSelectionComponent implements OnInit {

  constructor(private proposalService: ProposalService) { }

  @ViewChild(MatTable, {static: true}) kwTable: MatTable<any>;
  @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
  @Input() proposalId: string;

  keywordInput = new FormControl(null, Validators.required);

  dataSource: MatTableDataSource<Keyword>;
  displayedColumns = ['action', 'keyword', 'searches', 'competition', 'cpc'];
  suggestedKeywords: Keyword[] = [];
  selectedKeywords: string[] = [];

  fetchSuggestions(seeds?: string[]) {
    const ideas = {
      seeds: [],
      limit: 25
    };
    this.proposalService.getKeywordIdeas(this.proposalId, ideas).pipe(retry(3)).subscribe(res => {
      this.suggestedKeywords = res;
    });
  }

}

I'm not showing the complete component code here, but essentially:

I display a list of suggestedKeywords on the page, each triggering the addKeyword() method when clicked to add it to the dataSource. After clicking, the fetchSuggestions() method is called to update the suggestedKeywords list with new keywords.

The issue arises when multiple keywords are quickly selected, causing a request for each click to update the suggestedKeywords list. To prevent this and wait for a pause in interactions before making the request, I wanted to use debounceTime(). However, since my data source is just a simple array, I'm unsure how to make it trigger like an Observable.

Is there a way to mimic Observable behavior with array values so that an HTTP request is delayed after changes occur, similar to using Observables?

EDIT: Following suggestions in the comments, I used the from() operator. Should I define additional methods to listen for changes? Something akin to valueChanges() in FormControls.

After further reading, I'm considering using Subject, BehaviorSubject, etc.; however, I'm uncertain if this is the correct approach. Could someone provide an example of how to implement this?

Answer №1

To make your array behave like an observable, simply wrap it in the Observable.of() operator from RxJS

Answer №2

My approach involved utilizing a Subject to monitor changes and invoking its next() function whenever I modified the suggestedKeywords array, then subscribing to it as an observable.

The structure of my component ended up like this:

export class KeywordSelectionComponent implements OnInit {

  constructor(private proposalService: ProposalService) { }

  keywordInput = new FormControl(null, Validators.required);
  suggestedKeywords: Keyword[] = [];
  selectedKeywords: string[] = [];
  isLoadingResults = false;

  tag$ = new Subject<string[]>();

  ngOnInit() {
    this.tag$.asObservable().pipe(
      startWith([]),
      debounceTime(500),
      switchMap(seeds => this.getSuggestionsObservable(seeds))
    ).subscribe(keywords => {
      this.suggestedKeywords = keywords;
    });
  }

  addSuggestedKeyword(keyword: Keyword) {
    const suggestedKeyword = keyword;
    const existing = this.dataSource.data;

    if (!existing.includes(suggestedKeyword)) {
      existing.push(suggestedKeyword);
      this.dataSource.data = existing;
    }

    this.tag$.next(this.getCurrentTableKeywords());
  }

  fetchKeywordSearch(keyword: string) {
    this.isLoadingResults = true;
    this.keywordInput.disable();
    const search = {
      type: 'adwords',
      keyword
    };
    const currentData = this.dataSource.data;

    this.proposalService.getKeywordSearch(this.proposalId, search).pipe(retry(3)).subscribe(res => {
      currentData.push(res);
      this.dataSource.data = currentData;
    }, error => {},
    () => {
      this.isLoadingResults = false;
      this.keywordInput.enable();
      this.tag$.next(this.getCurrentTableKeywords());
    });
  }

  getCurrentTableKeywords(): string[] {}

  getSuggestionsObservable(seeds: string[] = []): Observable<Keyword[]> {
    const ideas = {
      type: 'adwords',
      seeds,
      limit: 25
    };

    return this.proposalService.getKeywordIdeas(this.proposalId, ideas).pipe(retry(3));
  }

}

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

"Utilizing Express's Jade middleware to efficiently handle and manage

Can you create a custom exception handler for errors in jade templates? For example: // server.js app = express(); app.set('view engine', jade); app.locals.js = function () { throw new Error('hello'); } // views/index.jade html != ...

Display the results from the API in a div using Vue.js

Currently working on implementing dynamic buttons to fetch data from an API call. Struggling with pushing the data array to the template and div. Here is my VueJS setup: var example = new Vue({ el: '#example', data: function () { ...

Tips for utilizing the index and style attributes when passing them to the Row function in React-Window

Currently, I am attempting to define the index and style parameters passed to the Row function in TypeScript. //https://github.com/bvaughn/react-window import * as React from "react"; import styled from "styled-components"; import { Fi ...

Exploring the capabilities of @angular/cli and integrating it with non-angular scripts can significantly

After upgrading my application to Angular 5, I decided to experiment with @angular/cli instead of using different webpack configs from the Angular starter package like I did previously. Our build process is fairly simple except for one aspect that I' ...

Message displaying successful AJAX response

I'm currently updating my AJAX request to make it asynchronous, but I am wondering if there is an equivalent to var response = $.ajax({ in the success function. Previously, my code looked like this: var response = $.ajax({ type : "GET ...

What is the process for removing a particular file from my bundle?

I am currently utilizing webpack to build my angular2/typescript application and have successfully generated two files, one for my code and another for vendors. However, I am in need of a third file to separate my config (specifically for API_ENDPOINT) whi ...

Arranging information extracted from an XML document following an ajax request

Here is a snippet of XML data sample to work with: <?xml version="1.0" encoding="ISO-8859-1"?> <CATALOG> <CD> <TITLE>Empire Burlesque</TITLE> <ARTIST>Bob Dylan</ARTIST> <COUNTRY>U ...

Steps to position images and text side by side in a grid layout

Trying to create a grid layout with profile images and text aligned next to each other, but struggling with CSS. If anyone could provide some guidance, that would be greatly appreciated! Here is the HTML code snippet: <div class="col-sm-3" ...

Utilizing JQuery to extract information from a JSON response

I've been struggling with accessing a specific piece of content within a JSON object. This is the code I'm using to fetch the data: function retrieveData(keyword){ $.ajax({ url: "https://openlibrary.org/api/books?bibkeys=ISBN ...

Can a constant value be dynamically defined in Typescript?

Trying to dynamically define a constant in Typescript has proven to be more challenging than I anticipated. Here's what I attempted: define(name: string, value: any): boolean { var undef; const name = value; return name == undef; } ...

Error code 2532 occurs when trying to access an object using square brackets in TypeScript

Encountered the ts error: Object is possibly 'undefined'.(2532) issue while trying to access the value of a field within an object, where the object key corresponds to a value in an Enum. Below is a concise example to showcase this problem: en ...

What is the best way to verify multiple email addresses simultaneously?

Is there a method to validate multiple email addresses entered by users in a textarea? My current approach involves using ng-pattern for validation. ...

Sorting and categorizing RxJS Observables

Learning about reactive programming is a new and sometimes challenging experience for me. If we have a list of events from a service called event[] The structure of an event is as follows: Event: { beginDate: Date, name: string, type: State } State: ...

PyScript <script type="py-editor"> Issue: SharedArrayBuffer cannot be used in an insecure environment

I am currently using PyScript to execute a basic Python script within my HTML file in order to show a pandas DataFrame. However, upon loading the page in the browser and attempting to run the code block by clicking the run button, I encounter an error rela ...

Obtain the URL from a Span Class located within a table

As I embark on my journey to learn javascript and jQuery, it's clear that my knowledge is quite rudimentary at this point. An attempt to make edits to a script written in Tampermonkey by a friend has led me down a path of extensive Googling with littl ...

The TypeScript type 'Record<string, string>' cannot be directly assigned to a type of 'string'

I can't seem to figure out why this code isn't working. I've encountered similar issues in the past and never found a solution. The snippet goes like this: type dataType = { [key: string]: string | Record<string, string>; ...

Animate exclusive fresh components

Exploring the functionalities of the latest animation API in Angular 2 has presented me with an interesting challenge: Within my parent component, I am utilizing *ngFor to display a series of child components. These child components are connected to a sim ...

The input feature in the Angular 4 Library allows users to easily

Hello everyone, I could really use some assistance with a problem I am facing. For some reason, I can't seem to make it work properly. I suspect that there might be an issue with the syntax I am using. Currently, I am in the process of developing Ang ...

Trigger a Vue method using jQuery when a click event occurs

I'm attempting to attach a click event to an existing DOM element. <div class="logMe" data-log-id="{{ data.log }}"></div> ... <div id="events"></div> Struggling to access external Vue methods within my jQuery click handler. A ...

Progressive series of observable conditions

The issue at hand: I am faced with the task of checking multiple conditions, some of which lead to the same outcome. Here is the current flow: First, I check if a form is saved locally If it is saved locally, I display text 1 to the user If not saved l ...