Tips for refreshing the service page in Ionic 2

One of my services is called "user-data", and its main function is to fetch "user data" when a request is received.

I have a specific page that is responsible for displaying this "user data". Upon loading the page, it retrieves the data and displays it.

Additionally, I have a menu with various buttons. Clicking on these buttons triggers a request to the "user-data" service to modify the data. After the data is modified, I want the page to be notified of the change and adjust accordingly.

The approach I take is as follows:

  • In the service: an event named "user:change" is published along with the updated data
export class UserData{
    users = [];
    ....
    //- if data is changed, 
    //- publish an event
    setUsers(users) {
        this.users = users;
        this.events.publish('user:change', users);
    }
}
  • In the page, subscribing to listen for this event
export class UserListPage {
    users = [];

    //- subscribe when the page is about to show
    ionViewWillEnter() {
        this.events.subscribe('user:change', this.updateUsers);
    }

    //- unsubscribe when leaving the page
    ionViewDidLeave() {
        this.events.unsubscribe('user:change', this.updateUsers);
    }

    //- update
    updateUsers(userEventData) {

        console.log('About to update');
        if (userEventData[0] instanceof Array) {
             this.users = userEventData[0];
        }
        console.log(this.users);
    }

} 

While everything works well within the updateUsers function, the issue arises when trying to assign a new value to this.users. It's quite perplexing.

On occasion, during debugging, an error message pops up saying: "attempted to assign to readonly property."

Any idea what might be causing this?

Answer №1

Instead of relying on traditional events, I recommend utilizing Observables for communication between components. While events can achieve the same outcome, using Observables in conjunction with a service to fetch data offers a more efficient approach. You can explore the code implementation in this live example on Plunker.

The flow of communication would be as follows:

Button / Page ---[calls service]---> Service ---[notifies other page and sends data]---> Page

Within the service, you can create an Observable that allows other components to subscribe and receive notifications once the data is available.

import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class UserDataService  { 

  private getDataObserver: any;
  public getData: any;

  constructor() {
    this.getDataObserver = null;
    this.getData = Observable.create(observer => {
        this.getDataObserver = observer;
    });
  }

  public getUserData() {
    // Simulated data to be sent to the page
    let userList = [
      { id: 1, name: 'user01 '},
      { id: 2, name: 'user02 '},
      { id: 3, name: 'user03 '}]

    // Simulating an HTTP request delay
    setTimeout(() => {
      // The next method will notify all subscribers and send the data.
      this.getDataObserver.next(userList);
    }, 1000);
  }
}

The next(...) method notifies all subscribers (in this case, the other component) and provides them with the data.

In the receiving component, simply subscribe to the observable to be informed when the data is ready and interact with the service like so:

import { Component } from "@angular/core";
import { UserDataService } from 'service.ts';

@Component({
  templateUrl:"home.html"
})
export class HomePage {

  users: any[];

  constructor(private service: UserDataService) {
      // Subscribing to the observable to fetch the data once it's ready
        this.service.getData.subscribe((userList) => {
      this.users = userList;
    });
    }

  public getData(){
    this.service.getUserData();
  }
}

Ensure to include the UserDataService in the providers array within the main App component to maintain a singleton service instance throughout the application.

import { Component } from "@angular/core";
import { ionicBootstrap, Platform } from 'ionic-angular/index';
import { HomePage } from './home.ts';
import { UserDataService } from 'service.ts';

@Component({
  template: '<ion-nav [root]="rootPage"></ion-nav>',
  providers: [UserDataService]
})
export class MyApp {
  constructor(private platform: Platform) {
    this.rootPage = HomePage;
  }
}

ionicBootstrap(MyApp);

Answer №2

I realized my mistake was in not organizing the "updateUser" function properly. After making some adjustments, the code below now functions correctly:

<pre>
export class UserListPage {
    users = [];

    //- Adding a subscription to be activated when the page is loaded
    ionViewWillEnter() {
        this.events.subscribe('user:change', (userData) => {
            console.log('Preparing for update');
            if (userData[0] instanceof Array) {
                  this.users = userData[0];
            }
            console.log(this.users);
        });
    }

    //- Unsubscribing when leaving the page
    ionViewDidLeave() {
        this.events.unsubscribe('user:change', ()=> {});
    }

}
</pre>

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

Update a BehaviourSubject's value using an Observable

Exploring options for improving this code: This is currently how I handle the observable data: this.observable$.pipe(take(1)).subscribe((observableValue) => { this.behaviourSubject$.next(observableValue); }); When I say improve, I mean finding a wa ...

Unable to initialize a public variable due to issues with Ionic Storage retrieval

I am currently facing an issue where I am trying to assign a token stored in the Ionic storage module to a public variable. However, when I attempt to set the token and then access it from another function, I encounter an undefined error. Here is the code ...

What is a Mongoose Schema type in TypeScript and how can it be used as a custom

https://i.stack.imgur.com/mtlRi.png Could anyone assist me with storing a custom object that includes attributes from the StationRating interface? ...

Data object constructor is not triggered during JSON parsing

Currently, I am retrieving data from a server and then parsing it into TypeScript classes. To incorporate inheritance in my classes, each class must be capable of reporting its type. Let me explain the process: Starting with the base class import { PageE ...

Simple method for adapting async/await function to function smoothly with observables

From my understanding, it's not recommended to use async/await methods in Angular. Therefore, I am exploring alternatives to achieve the desired functionality without using those methods. Currently, I am utilizing the canActivate function which call ...

Issue: Unable to load the file named 'script.ts' while employing chrome.scripting.executeScript

Currently, I am working on developing a chrome extension using Vite with React and Typescript along with CRXJS. This is my initial project in this domain. The issue I am encountering is related to executing a script on the current tab when a button is clic ...

Encountering difficulties testing MatTable row population in Karma testing

Can someone please assist me in identifying the issues with my coding method? I attempted to replicate the techniques demonstrated in this tutorial on Harnesses Here is an Angular component that consists of a simple data table (MatTable) connected to a re ...

Choose only the options that are present in both arrays

I am working on creating a multiple select feature that displays all nodes, but only checks the ones that are present in 2 arrays. My front end is developed using Angular 8 and TypeScript. private mountSelect(nodesInRelation, lineApiKey) { console.lo ...

Drizzle-ORM provides the count of items in a findMany query result

Hello there, I'm currently experimenting with the Drizzle ORM and imagine I have this specific query const members = await trx.query.memberTable.findMany({ with: { comments:true } }) I'm wondering how I can retrieve the total count of me ...

AgGrid's magical dropdown feature

Struggling to integrate a bootstrap-4 dropdown menu with AgGrid, I'm facing an issue where the data table overlaps the dropdown when the html is present. Attempts to increase the z-index have not yielded results. Below is the html code snippet: < ...

Why is npm installing a version of Angular CLI that is incompatible with its usage?

After using nvm to install node v16.13.2, as well as npm version 8.1.2, I discovered that this setup did not include the Angular CLI by default. To rectify this, I ran npm install -g @angular/cli. However, upon checking the version of Angular CLI with ng v ...

Explanation on How to utilize the $( document ).ready() jQuery function within the ngAfterViewInit() on a Component class using Angular 2

This is the code snippet: constructor(private el: ElementRef) { } ngAfterViewInit() { this.loadScript('app/homepage/template-scripts.js'); } ...

Step-by-step guide to start an AngularJs application using TypeScript

I have developed an AngularJS App using TypeScript The main app where I initialize the App: module MainApp { export class App { public static Module : ng.IModule = angular.module("mainApp", []) } } And my controller: module MainApp { exp ...

Tips on incorporating dynamic expressions within ngFor loops?

Is there a way to dynamically display specific properties from objects in an array (list: any[]) within an *ngFor loop in Angular? I am currently working on a component called ListComponent that is responsible for rendering a list of items. The parent com ...

ng-bootstrap component 404 error on final angular2 release

angular2 final release. ng-bootstrap alpha v.5 bootstrap components are functioning on html, however when attempting to import them like this import {ViewChild} from "@angular/core/src/metadata/di"; import {NgbDropdown} from "@ng-bootstrap/ng-bootstrap/d ...

How to send a dynamic URL parameter to a function in Next.js TypeScript without using implicit typing

When utilizing the useRouter function with a parameter of type string, the following error is encountered: Type 'string | string[] | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type & ...

The data source retrieved through the "get" API method is missing from the mat-table

Recently, I've started working with angularCLI and I'm facing an issue in creating a table where the dataSource is fetched from a fake API. Let me share my component class: import { Component, OnInit } from '@angular/core'; import { Fo ...

Using local variables in Angular2 templates

For the specific scenario discussed below, I have assigned the local variable #input to multiple radio buttons. My goal is to select the radio button within the <tr> when it is clicked. Surprisingly, the provided code functions as expected, yet the ...

Typical approach to receiving a transformed object from an HTTP service

One of the services I provide includes a method with the following implementation: public fetchCrawls(page: number): Observable<ICrawl[]>{ return this._http.get(this._crawlsURL + page) .map((res: Response) => { ...

When working on styling a different Styled Component, how should one define the type of props required?

I'm currently working on a NextJS project using styled components and typescript. I have customized a div element like this: export const ClippedOverlay = styled( ( props: React.DetailedHTMLProps< React.HTMLAttributes<HTMLDivElement& ...