Updating the countdown label in NativeScript and Angular

I am currently working on a timer countdown component and have the following code:

@Component({
  moduleId: module.id,
  selector: 'time-countdown',
  template: `<StackLayout>
                 <Label text="{{timeRemaining}}" ></Label>
             <StackLayout>`
})
export class TimeCountdownComponent implements OnInit {
    @Input() periodDetails  :any; 
    private timeRemaining     :string = "";
    private units           :string = "";

    constructor( private ps: PeriodService) {}

    ngOnInit() {
      this.periodDetails.nextPeriodStartDate = this.ps.getNextPeriod(this.periodDetails);
      console.log("TIME COUNTDOWN: init => " + this.periodDetails.nextPeriodStartDate.toString() )
      setInterval(() => {
          this.getTimeRemaining()
      }, 1000)
    }           

    getTimeRemaining(){
      let trObject = this.ps.getTimeRemaining(this.periodDetails.nextPeriodStartDate);
      this.timeRemaining = trObject.time;
      this.units = (!trObject.units) ? "days": "";
      console.log("TIME COUNTDOWN: Tick => " + this.timeRemaining )
    }          
  }

The issue I'm facing is that while the correct units and time remaining are displayed in the console, they are not showing up in the label. I have tried using Observable.timer().subscribe, Observable.interval().subscribe, and changing the template to "[text]='timeRemaining'", but none of these solutions seem to work.

This particular component is added dynamically by the user (as discussed in this post). Interestingly, when I click on the "+" button to add a new timer, the time briefly appears for a fraction of a second before disappearing again. Can anyone provide insights into what might be causing this or how I can troubleshoot it?

EDIT: After conducting extensive research and testing, I have found an interim solution. When I use this component as the root component of the app, the following code works:

@Component({
  moduleId: module.id,
  selector: 'time-countdown',
  template: `
            <StackLayout>
              <Label [text]="timeRemaining | async" ></Label>
            <StackLayout>
            `
})

export class TimeCountdownComponent implements OnInit {
    @Input() periodDetails: any;
    private timeRemaining: any;

    ngOnInit(){
        this.periodDetails.nextPeriodStartDate = this.ps.getNextPeriod(this.periodDetails);
        this.timeRemaining = new Observable<string>((observer: Subscriber<string>) => {
          setInterval(() => observer.next(this.getTimeRemaining().time),1000);
        });
    }


    constructor(private ps: PeriodService ) {}


    getTimeRemaining() {
        let tr = this.ps.getTimeRemaining(this.periodDetails.nextPeriodStartDate);
        console.log(tr.time);
        return tr;
    }
}

However, if I nest this component into another component, it fails to display the time remaining in the template even though it is logged in the console. Can someone help me understand what might be causing this discrepancy?

Answer №1

When utilizing an observable, it is necessary to employ the async pipe like so:

<Label [text]="timeRemaining | async" ></Label>
. If not, alternatives such as NgZone or zonedCallback can be used.

ZonedCallback

declare var zonedCallback: Function;

@Component({
    moduleId: module.id,
    selector: 'time-countdown',
    template: `<StackLayout>
                 <Label text="{{timeRemaining}}" ></Label>
             <StackLayout>`
})
export class TimeCountdownComponent implements OnInit {
    @Input() periodDetails: any;
    private timeRemaining: string = "";
    private units: string = "";

    constructor(private ps: PeriodService) { }

    ngOnInit() {
        this.periodDetails.nextPeriodStartDate = this.ps.getNextPeriod(this.periodDetails);
        console.log("TIME COUNTDOWN: init => " + this.periodDetails.nextPeriodStartDate.toString())
        setInterval(() => {
            this.getTimeRemaining()
        }, 1000)
    }

    getTimeRemaining() {
        let trObject = this.ps.getTimeRemaining(this.periodDetails.nextPeriodStartDate);
        zonedCallback(() => {
            this.timeRemaining = trObject.time;
            this.units = (!trObject.units) ? "days" : "";
        })
        console.log("TIME COUNTDOWN: Tick => " + this.timeRemaining)
    }
}

NgZone

import { NgZone } from "@angular/core";
@Component({
    moduleId: module.id,
    selector: 'time-countdown',
    template: `<StackLayout>
                 <Label text="{{timeRemaining}}" ></Label>
             <StackLayout>`
})
export class TimeCountdownComponent implements OnInit {
    @Input() periodDetails: any;
    private timeRemaining: string = "";
    private units: string = "";

    constructor(private ps: PeriodService, private ngZone: NgZone) { }

    ngOnInit() {
        this.periodDetails.nextPeriodStartDate = this.ps.getNextPeriod(this.periodDetails);
        console.log("TIME COUNTDOWN: init => " + this.periodDetails.nextPeriodStartDate.toString())
        setInterval(() => {
            this.getTimeRemaining()
        }, 1000)
    }

    getTimeRemaining() {
        let trObject = this.ps.getTimeRemaining(this.periodDetails.nextPeriodStartDate);
        this.ngZone.run(() => {
            this.timeRemaining = trObject.time;
            this.units = (!trObject.units) ? "days" : "";
        })
        console.log("TIME COUNTDOWN: Tick => " + this.timeRemaining)
    }
}

Answer №2

Don't forget to include the context when calling the method. Try using "this" like getTimeRemaining(this) to properly pass the context.

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

Unable to access specific data from the JSON string retrieved from the backend, as it is returning a value of undefined

After receiving a JSON string from the backend, my frontend is encountering issues when trying to index it post using JSON.parse(). The indexed value keeps returning as undefined, even though it's a JSON object literal and not within an array. For th ...

Can a File Object be transmitted to an AWS Lambda function via API Gateway using JavaScript?

Can a JavaScript File Object be passed from a browser to AWS Lambda via API Gateway (ultimately to S3)? I am working with TypeScript and React. Environment Frontend TypeScript React AWS Amplify (for API module) Backend(AWS Lambda) Node.js Expecta ...

The issue with session storage persisting even after closing the iframe

Encountering a persistent issue where the sessionStorage remains populated even after closing an iframe and opening another one with the same destination. I assumed that the sessionStorage would be reset and start afresh each time. The iframe is contained ...

Generating TypeScript Type Definitions for dynamic usage

In my client server application, I use REST calls for communication. To avoid using the wrong types by mistake, I have defined all RestCalls in a common file (excerpt): type def<TConnection extends Connections> = // Authentication ...

Transforming an array of strings into an array: a guide

An API call is returning an object with the following structure: data = { ... filter: "[1,2,3]" ... } I need to convert the string of array into an actual array of numbers, like [1,2,3]. Thank you! ...

The element does not recognize the property 'width' since it is not defined in the type of 'GlobalEventHandlers'

I'm trying to determine the size of an image using JavaScript, but I encountered a TypeScript error: const img = new Image(); img.onload = function() { alert(this.width + 'x' + this.height); } img.src = 'http://www.google.com/intl/en_ ...

What is the best way to add a service to a view component?

I am facing an issue with my layout component where I am trying to inject a service, but it is coming up as undefined in my code snippet below: import {BaseLayout, LogEvent, Layout} from "ts-log-debug"; import {formatLogData} from "@tsed/common/node_modul ...

Ways to dynamically emphasize text within ngFor loop

Within my ngFor loop, I have a set of rows. <div *ngFor="let block of data;"> <div class="class-row"> <div class="left">A Label:</div> <div class="right">{{block.key1}}</div> </div> <div class="clas ...

The Axios and TypeScript promise rejection error is displaying an unknown type- cannot identify

Currently, I am encountering an issue where I am unable to utilize a returned error from a promise rejection due to its lack of typability with Typescript. For instance, in the scenario where a signup request fails because the username is already taken, I ...

How to Use an Object Created from a Different Class in TypeScript

Scenario In the development process, I am using an auth.service.ts. This service is responsible for fetching user information from the database upon login. The retrieved data is then used to create a new user object. Here is a snippet of the code: user: ...

hide elements only when there is no string to display in Angular2/Typescript

As I experiment with my javascript/typescript code, I've encountered an issue where a string is displayed letter by letter perfectly fine. However, once the entire string is shown, the element containing it disappears and allows the bottom element to ...

Steps to resolve the 'Cannot assign value to userInfo$ property of [object Object] that only has getter' issue in Angular

I am currently in the process of building a web application using NGXS, and I'm encountering a specific error that I'm trying to troubleshoot. The issue arises when I attempt to fetch data from an API and display it within a column on the page. D ...

The theming feature in Angular 5 with Bootstrap 4 and Bootswatch seems to be malfunctioning

Having trouble implementing bootswatch themes with angular 5 and bootstrap 4? I've added the following to styles.scss: @import "~bootswatch/dist/cerulean/variables"; @import "~bootstrap/scss/bootstrap"; @import "~bootswatch/dist/cerulean/ ...

Learn how to display a tooltip for every individual point on a Highcharts network graph within an Angular

I am currently working on developing network graphs using highcharts and highcharts-angular within my Angular application. I have successfully managed to display the graph with datalabels, but now I need to implement tooltips for each point or node on the ...

When using the delete method in Next.js, req.body is undefined

Strangely, I cannot figure out the reason why fetching data and inserting it into the body of my response results in an "undefined" message in the console. Interestingly, I have two nearly identical components - one employing a POST method with a populated ...

I need RxJs to return individual elements to the subscriber instead of an array when using http.get

I've been developing an Angular 2 app (RC5) with a NodeJS backend RESTful API integration. One specific route on the backend returns an array of 'Candidates': exports.list = function (req, res, next) { const sort = req.query.sort || null ...

Angular Space-Friendly Table

After attempting to code the sample in Angular, I realized it wasn't what I was looking for. <table> <th >Number</th> <th >Merchant Name</th> ...

Testing an Angular service call

I am currently testing whether a button click will trigger a method call in the service. Here is an excerpt of the component content: ngOnInit() { try { //GET ALL ITEMS this.service.getAll().pipe(untilDestroyed(this)).subscribe((result) =& ...

Guide to creating jest unit test for an observable variable exclusively utilized in a template resulting in the error "Property 'pipe' of undefined cannot be read"

Seeking help with creating unit tests for an Angular component that utilizes a constructor and observable variable in the HTML template. Below is the code snippet I am having issues with: voice-summary.component.ts export class VoiceSummaryComponent { v ...

Guide to exporting a ReactJS + Typescript component to be used in Vanilla JavaScript and HTML

I have a ReactJS component along with its sub-components styled with CSS. I'm looking for a way to export my component for VanillaJS and HTML without having to import React@17 or 18. If there is an easier method or any alternative suggestions instead ...