Changing properties of a parent component from a child component in Angular 2

Currently, I am utilizing the @input feature to obtain a property from the parent component. This property is used to activate a CSS class within one of the child components.

Although I am successful in receiving the property and activating the class initially, it seems to work only once. The property received from the parent is of boolean data type. When I attempt to change this status to false from the child component, it does not reflect back in the parent component.

To see the code in action, you can check out this Plunkr: https://plnkr.co/edit/58xuZ1uzvToPhPtOING2?p=preview

app.ts

import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { HeaderComponent } from './header';
import { SearchComponent } from './header/search';

@Component({
  selector: 'my-app',
  template: `
    <app-header></app-header>
  `,
})
export class App {
  name:string;
  constructor() {
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, HeaderComponent, SearchComponent ],
  bootstrap: [ App ]
})
export class AppModule {}

header.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-header',
  template: `<header>
              <app-search [getSearchStatus]="isSearchActive"></app-search>
              <button (click)="handleSearch()">Open Search</button>
            </header>`
})
export class HeaderComponent implements OnInit {
  isSearchActive = false;

  handleSearch() {
    this.isSearchActive = true
    console.log(this.isSearchActive)
  }

  constructor() { }
  ngOnInit() { }
}

header/search.ts

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-search',
  template: `<div id="search" [class.toggled]="getSearchStatus">
              search 
              <button  (click)="getSearchStatus = false" class="close">Close Search</button>
            </div>`
})
export class SearchComponent implements OnInit {
  @Input() getSearchStatus: boolean;

  constructor() { }

  ngOnInit() {

  }
}

While examining the provided plunker, you'll notice that the open search function stops working after the first usage. Following the closure of the search, attempting to trigger it again proves to be ineffective.

My query pertains to whether using @input is fitting for this particular scenario. Any assistance in rectifying this issue would be greatly appreciated. (Please update the Plunker with solutions.)

Answer №1

To achieve two-way data binding, you must utilize a specific technique.

@Input() only facilitates one-way data binding. To establish two-way data binding, you must include an @Output() that corresponds to the property and appends "Change" as a suffix.

@Input() getStatus: boolean;
@Output() statusChange = new EventEmitter<boolean>();

Whenever you need to inform the parent component about changes made to your property, you should use the following notification:

this.statusChange.emit(updatedValue)

In the parent component, you have to use the banana-in-a-box notation for that particular property:

[(getStatus)]="myBoundProperty"

Additionally, you can bind to the property and trigger a callback function in the child component when it undergoes a change:

[getStatus]="myBoundProperty" (statusChange)="myCustomCallback($event)"

For more details, refer to this example on Plunker.

Answer №2

Here's another technique: utilize rxjs/BehaviorSubject to communicate status changes between different components.
Take a look at the example.
I labeled the subject with a 'Rxx' suffix, so the BehaviorSubject for searchStatus will be known as searchStatusRxx.

  1. Initialize it in the parent component like
    searchStatusRxx = new BehaviorSubject(false);
  2. Pass it to the child component using @Input
  3. In the child template, use the async pipe.
  4. In both the parent and child components, call searchStatusRxx.next(value) to update the value.

Answer №4

Here is another alternative method. Check out this Plunkr. The goal is to have a single source of truth, which we can achieve by placing it inside the child component.

  • Initialize searchStatus in the child component: searchStatus = false
  • In the parent template, access the child component instance with #as or any desired name.
  • Modify the searchStatus variable in the parent component using #as.searchStatus, and in the child component using this.searchStatus.

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

Discover the simplicity of incorporating pagination into an HTML table with Angular Material

My goal is to implement pagination on my webpage, displaying 3 rows per page and enabling navigation through pages using Angular Material pagination. In usersComponent.ts, I retrieved data from an API: import { Component, OnInit, ViewChild } from '@an ...

NestJS: Specify the data type for @Body()

Consider the code snippet below: @Post() public async createPet(@Body() petDetails: PostPetDto): Promise<any> { } In this scenario, the type of @Bod() petDetails defaults to plain/any instead of the declared type of PostPetDto. What is the recommen ...

What is the process for obtaining an app icon from the store using Angular?

Currently, I am working on an app using ionic, angular, and Cordova. Within this app, there are links to other apps available in the app store. My main query is: Is there a way to retrieve the icons of these apps from the store? I aim to display these ic ...

What is the best method for launching a Node.js (Express) app on a live server automatically?

My Angular app relies on an express backend. What is the best way to deploy this application on a remote server so that it always runs smoothly? ...

Using RxJS pubsub to transform an Observable<any> into a string or object

My current pubsub service implementation is as follows: export class PubSubService { subjects: Map<string, Subject<any>> = null; constructor() { this.subjects = new Map<string, Subject<any>>(); } publish(data: { key: ...

In TypeScript, develop a specialized Unwrap<T> utility type

After successfully creating a helper type to unwrap the inner type of an Observable<T>, I began wondering how to make this type completely generic. I wanted it to apply to any type, not just Observable, essentially creating Unwrap<T>. Here is ...

Error: Element type is invalid: a string was anticipated, but not found

I recently experimented with the example provided in React's documentation at this link and it functioned perfectly. My objective now is to create a button using material-ui. Can you identify what is causing the issue in this code? import * as R ...

Enhance your website with unique and custom fonts using

I am utilizing this repository. How can I incorporate custom fonts into my project? I have created a folder named "fonts" within the assets directory and placed my fonts there. fonts.scss @font-face { font-family: 'Lato'; src: url('../ ...

Utilizing Mongoose to fetch data from Atlas MongoDB for integration into an Angular application

I recently made some updates to my signup page by adding a new input field for the user's name and adjusting the schema settings accordingly. How can I now retrieve this name to use in both my post-list component and post-create component? Here is an ...

Adding query parameters to an Angular route

In my app's routing module, I have set up the following routes: const routes: Routes = [ { path: "", redirectTo: "/smart-parking/dashboard", pathMatch: "full" }, { path: "locations-create", component: AddLoc ...

The preflight request in Angular2 is being rejected due to failing the access control check: The requested resource does not have the 'Access-Control-Allow-Origin' header

I encountered an issue while attempting to execute a basic POST request to establish an account using an API in .NET. The process fails with the mentioned warning title. Interestingly, performing the same request in Postman (an API testing tool) yields a s ...

Learn how to access nested arrays within an array in React using TypeScript without having to manually specify the type of ID

interface UserInformation { id:number; question: string; updated_at: string; deleted_at: string; old_question_id: string; horizontal: number; type_id: number; solving_explanation:string; ...

Data binding in Angular 2: Connecting components

Is it possible to establish a connection between two components that are working with related objects? One of the components is dedicated to filtering, while the other displays the data results. By applying filters such as checkboxes, the displayed data ...

Anticipate the absence of a specific object length

I have an Object that I need to test for null: getLastTeamUpdatedItemLogBuffer(): IBufferElement { const storageItems = this.storageSvc.getItem(StorageKey.lastTeamUpdatedItem, true) as IBufferElement; return storageItems || null; } This is the IBufferE ...

Limiting the defaultValue of a select to one of the values of its options in TypeScript: A guide

Is there a way to configure the Select component's properties so that the defaultValue is limited to one of the predefined options values ("au" | "nz" in this scenario)? const countryOptions = [ { value: "au", l ...

In a Next.js project, Typescript seems to be overlooking errors related to proptype definitions and function types

Greetings everyone! I am currently working on a project using TypeScript and have implemented various rules and elements. However, I am facing issues with type errors for functions and props. Essentially, when using any function, it is necessary to specify ...

Step-by-step guide for resolving the issue of "Observable.share is not recognized as a function" in Angular 2

When working with cache structure in Ionic 2, I often encounter an error when defining an observable array to store data retrieved from the server. How can I troubleshoot this issue and resolve it? marketArray : Observable<any>; /* GLOBAL */ th ...

Tips on using class-validator @isArray to handle cases where only a single item is received from a query parameter

Currently, I am attempting to validate a request using class-validator to check if it is an array. The inputs are sourced from query parameters like this: /api/items?someTypes=this This is what my request dto resembles: (...) @IsArray() @IsEn ...

Managing external dependencies in NX & Angular compatible libraries

I am working with a monorepo using NX & Angular where I am publishing some libraries to NPM. In my setup, I have the following structure: apps only_App libs lib_A // v1.0.0 lib_B // v1.0.0 lib_C // v1.0.0 The library lib_A depends on both lib_ ...

Module 'next-intl/client' cannot be located

When I run npm test, I encounter the following error: 'next-intl/client' module not found jest.mock( | ^ 22 | 'next-intl/client', 23 | (): Record<string, unknown> => ({ 24 | usePathname: ...