how to identify initial change using signal input in Angular

In the previous Angular codebase, we utilized:

@Input() foo = '';

ngOnChanges(changes: Record<string, SimpleChange | undefined>): void {
  if (changes['foo']) {
    if (changes['foo'].firstChange) {
      // handling logic for first change
      console.log('first change', changes['foo'].currentValue);
    } else {
      // different logic for subsequent changes
      console.log(
        '2+ changes',
        changes['foo'].previousValue,
        changes['foo'].currentValue
      );
    }
  }
}

Is there a way to replicate this functionality using the new signal input and effect?

I've come across suggestions to convert the signal into an observable and utilize pairwise, but it seems that pairwise doesn't emit for the initial value at all.

Check out this simple example to experiment with: https://stackblitz.com/edit/stackblitz-starters-ymnhaw?file=src%2Fcmp%2Fcmp.component.ts

The reason for my inquiry is related to the discussions on RFC for signal components, where it's noted that

  1. Signal-based components will maintain only the lifecycle methods ngOnInit and ngOnDestroy
  2. ngOnChanges - used for monitoring input changes. With signal-based inputs, computed can be applied to generate new values, or effects can be utilized for reactive side-effects.

https://i.sstatic.net/zyB1s.png

Answer №1

If you want to keep track of the previous value, you can store it in a private property and update it with the latest value after handling any changes:

  value = input.required<number>();
  #prev: number | null = null;

  #changes = effect(() => {
    console.log(this.value(), this.#prev);
    // handle your changes here

    // then update the previous value
    this.#prev = this.value();
  });

Check out this example for reference: https://stackblitz.com/edit/stackblitz-starters-whk2kj?file=src%2Fmain.ts

Answer №2

I'm encountering a similar issue. It appears to be a missing element of functionality that is required in more recent versions of Angular.

However, here's my approach to tackling it in Angular 17/18 using effect:

foo = input<string>();

private prevFoo: string;

private onFooChanged = effect(
  () => {
    const foo = this.foo();

    if (this.prevFoo === undefined) {
      // Initial change, perform certain actions...
    } else {
      // Subsequent changes, perform different actions...
    }

    this.prevFoo = foo;
  }
);

This seems like a lot of code for something so straightforward. Hopefully, they will introduce a more streamlined solution for this.

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

Error: Unable to assign the 'schedule' property to a null value

I'm currently developing a scheduling application using React.js and have implemented a draggable scheduling feature for users to indicate their availability. Everything seems to be working smoothly, except for one pesky error message: TypeError: Cann ...

Is it possible for jQuery to operate on an HTML structure that is stored in memory

Exploring In-Memory HTML Structures with jQuery. Take a look at this snippet of HTML code: <div id="template" hidden="hidden"> <div class="col-md-3 margin-bottom20"> <p id="template-title" class="text-capitaliz ...

When attempting to import a react component written with TypeScript to npm, receiving an 'undefined' error

I recently encountered an issue when trying to publish my custom React component developed with TypeScript on npm. Although the publishing process was successful, I faced an error upon importing the npm package into a new React project: Error: Element ty ...

Mastering Bootstrap 4 flexbox for optimal content filling: A comprehensive guide

I am currently working on an angular app integrated with bootstrap 4. The challenge I am facing is related to the layout design. I have a fixed navbar at the top and a content area below it. Within the content area, I have a div that includes header and fo ...

Unlocking the pathway to obtaining client_secret credentials in Keycloak

I seem to be having trouble in the Keycloak dashboard. I can't seem to find the necessary credentials to access the client_secret code. see the image(dash) I am currently using version 23 of Keycloak, and I require the client_secret to gain access to ...

Analyzing a string using an alternative character

I want to convert the string "451:45" into a proper number. The desired output is 451.45. Any help would be appreciated! ...

When trying to check a condition in Angular using a boolean, a TypeError is generated stating that a stream was expected instead of the provided 'false' value

Error: In global-error-handler.ts file at line 42, a TypeError has occurred. It states: "You provided 'false' where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable." Below is the s ...

How can I customize the error message for chai expect in my mocha unit test?

I'm working on a mocha test that uses chai's expect function: it("should parse sails out of cache file", async () => { const sailExtractor = new Extractor(); const result = await sailExtractor.extract("test.xml"); try { e ...

Trouble shooting: Angular 2 Http get request not firing

I'm facing an issue where nothing happens when I try to subscribe to my observable. There are no errors in the console or during the build process. Below is the code snippet that I am using: My service getBlueCollars(): Observable<BlueCollar[]& ...

The RxDB Angular2-cli error message. "Cannot assign a 'Promise<void>' to a 'Promise<any>' parameter."

https://i.sstatic.net/50vu6.png I've been grappling with getting RxDB to function properly in a fresh project I initiated using the Angular CLI. Here's my process: ng new <Projectname> After that, I installed RxDB by running: npm instal ...

Angular 2 release candidate 3 encounters issues with unfulfilled dependencies

Having encountered an issue with npm, specifically related to dependencies while using packages.json from the official Angular2 site's quick start guide. Yesterday everything was functioning correctly, but today I am facing difficulties as npm is unab ...

Sharing information between different pages in NEXT.js version 14

After performing a fetch and receiving a successful response containing data as an object, I use router.push to redirect the page to another one where I want to display the fetched data. const handleSubmit = async (event: any) => { event.preventDefa ...

Trouble with displaying cell content in ag-grid within an Angular application

I have implemented ag-grid in my Angular project and I am trying to redirect to a link when a specific cell is clicked. Currently, I have a new value coming from an API which is nested inside an object in an array. For example, the object is dto-> dat ...

Trigger API call in the background if Angular's HTTP observable does not provide a response within a specified time frame

In my Ionic/Angular application, I have implemented HTTP API calls using Angular and RxJS observables. this.http .post('https://API URL', data, { headers: headers }).map(response => response.json()).subscribe( (res) =& ...

Tips to successfully save and retrieve a state from storage

I've encountered a challenge while working on my Angular 14 and Ionic 6 app. I want to implement a "Welcome" screen that only appears the first time a user opens the app, and never again after that. I'm struggling to figure out how to save the s ...

:host-selector for Angular Material dialog

I am currently working with a dialog component provided by angular-material and I need to customize the appearance of the popup dialog. I am aware that there is some support for styling through the component generation: let dialogRef = dialog.open(MyDi ...

Include a hyperlink within every row - ngx-datatable

I am brand new to using Angular. My goal is to have a link on each row of ngx-datatable that directs me to another page when clicking on the first column of each row. This new page should be based on the row id. For example, if I have a table listing cours ...

Transform the object type into Angular's Type<T>

After working with a list of components, an AnyComponent type, and a function to locate a specific component, I encountered an issue: const components = [Comp1, Comp2, Comp3 ...]; type AnyComponent = typeof components[number]; findComponent(id: string): ...

The index type cannot be specified as 'null'

I am currently working with Typescript and have strict null checking enabled. Whenever I try to compile the code below, I receive an error stating "type 'null' cannot be used as an index type." function buildInverseMap(source: Array<string | ...

What is the best way to generate a switch statement based on an enum type that will automatically include a case for each enum member?

While Visual Studio Professional has this feature, I am unsure how to achieve it in VS Code. Take for instance the following Colors enum: enum Colors { Red, Blue, When writing a switch statement like this: function getColor(colors: Colors) { swi ...