Sharing variables between Angular 2 components: An in-depth guide

Looking for a way to change a variable in a group of child components, I have this component for an editable form control that toggles between view states

import {
    Component,
    Input,
    ElementRef,
    ViewChild,
    Renderer,
    forwardRef,
    OnInit
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

const INLINE_EDIT_CONTROL_VALUE_ACCESSOR = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => InlineEditComponent),
    multi: true
};

@Component({
  selector: 'inline-edit',
  templateUrl: 'inline-edit.html',
  providers: [INLINE_EDIT_CONTROL_VALUE_ACCESSOR],
})
export class InlineEditComponent implements ControlValueAccessor, OnInit {

    @ViewChild('inlineEditControl') inlineEditControl: ElementRef;
    @Input() label: string = '';
    @Input() type: string = 'text';
    @Input() required: boolean = false;
    @Input() disabled: boolean = false;
    private _value: string = '';
    private preValue: string = '';
    public editing: boolean = false;
    public onChange: any = Function.prototype;
    public onTouched: any = Function.prototype;

    get value(): any {
        return this._value;
    }

    set value(v: any) {
        if (v !== this._value) {
            this._value = v;
            this.onChange(v);
        }
    }

    writeValue(value: any) {
        this._value = value;
    }

    public registerOnChange(fn: (_: any) => {}): void {
        this.onChange = fn;
    }

    public registerOnTouched(fn: () => {}): void {
        this.onTouched = fn;
    }

    constructor(element: ElementRef, private _renderer: Renderer) {
    }

    ngOnInit() {
    }

}


<div>
  <div [hidden]="!editing">
    <input #inlineEditControl [required]="required" [name]="value" [(ngModel)]="value" [type]="type" [placeholder]="label" />
  </div>
  <div [hidden]="editing">
    <label class="block bold">{{label}}</label>
    <div tabindex="0" class="inline-edit">{{value}}&nbsp;</div>
  </div>
</div>

Trying to come up with a directive to utilize these components and switch the editing flag to true

export class EditForm {
   //Thinking of doing something like this:
   public toggleEdit(fn: () => {}): void {
      var editableFormControls = $('#selector: 'inline-edit');
      editableFormControls.forEach(control => control.editing = true)
   }     
}

Interested in finding a way to select all the editable form controls and set the editing flag to true in each of them. Any suggestions?

Answer №1

In order to maintain the state across components, it may be necessary to create a service that stores the state and allows child components to subscribe to changes in the state. The parent component can then push any changes to this centralized state.

import {Component, NgModule, VERSION, Input} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {BehaviorSubject} from 'rxjs/BehaviorSubject';

export class EditableService {
  subject = new BehaviorSubject(true);
  getAsObservable() {
    return this.subject.asObservable();
  }
}

@Component({
  selector:'editable',
  template: '<div>i am editable {{ x | async}}</div>'
})
export class Editable {
  constructor(private editableService: EditableService) {
    this.x = editableService.getAsObservable();
  }
}

@Component({
  selector: 'my-app',
  template: `
    <editable></editable>
    <editable></editable>

    <hr/>
    <button (click)="change()">change</button>
  `,
  providers: [EditableService]
})
export class App {
   change() {
    this.editableService.subject.next(false);
   }

   constructor(private editableService: EditableService) {
    this.name = `Angular! v${VERSION.full}`;
  }

 }

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

"Streamlining data entry with an uncomplicated HTML form input that accepts multiple values from a

As I understand it, a barcode scanner functions as nothing more than a keyboard that transmits keycode 13 after each scan. My task is straightforward: I have a basic form with only one input field and I want the ability to scan numerous barcodes and then c ...

Modifying text dynamically in AngularJS by cycling through an array of strings

Is it possible to create a text carousel in my angular controller without using an infinite loop? For example: //html <span> {{ notes }}</span> //angular controller var i = 0; var array = ["A", "B", "C", "D", "E"]; while (true ...

Issue with Thickbox - showing up towards the end of the page

I'm encountering a strange issue with a PHP page in Wordpress. When I include an inline Thickbox on the page and try to open it, the Thickbox appears at the very bottom of the page, below the footer. Interestingly, I copied the generated HTML code an ...

Setting up an angular2 web application on an Nginx server and forwarding HTTP requests to the backend API for

Seeking assistance with setting up angular2 routes and proxying http requests to a rest api on a separate server Currently, I have an angular2 web application running on an nginx server which serves the static html files. The rest api that the application ...

Tips for modifying JSON property names during the parsing process

As outlined in the JSON.parse documentation, a reviver function can be utilized to modify the value of each property within the JSON data. Here is an example: JSON.parse('{"FirstNum": 1, "SecondNum": 2, "ThirdNum": 3}', function(k, v) { return ...

Revamp the current webpage to display attribute values in textual format

As I peruse a webpage, I notice that there is room for improvement in terms of user-friendliness. The page is filled with a list of movie titles, each accompanied by a link to IMDb. However, the IMDB user rating is only visible when hovering over the titl ...

What steps can I take to create a slideshow with dynamic animations?

I am trying to create a unique category display by turning it into a slider. When the user clicks on any category, I want it to move to the left and become larger. To see an example of how the sliding effect works, check out this link: slideshow https://i ...

What is the method for obtaining the ID of a dynamically generated DropDownList and verifying if its value has been altered?

I successfully created a view with the help of Steven Sanderson's blog where a dynamic number of textboxes and DropDownList are generated. Everything is functioning properly. However, I would like to ensure that the form cannot be submitted until each ...

How to trigger an Angular JS route without loading a view

Could someone help me with calling the /auth/logout url to get redirected after a session is deleted? app.config(['$routeProvider',function($routeProvider) { $routeProvider .when('/auth/logout',{ controller:'AuthLo ...

Why is the Slick Slider displaying previous and next buttons instead of icons?

I'm currently working on creating a slider using the slick slider. Everything seems to be functioning properly, but instead of displaying arrows on the sides, it's showing Previous and Next buttons stacked vertically on the left side. It appears ...

Understanding the scope of a variable within a function in JavaScript

Working with JSON, I am attempting to determine the total number of elements in the response. $.getJSON("/api/getEvents", function(data) { $.each(data, function(key, event) { var count = 10; $.getJSON("/api/getUsers", f ...

Finding the correct path for ts-loader with webpack version 2.2.1 within a script

When running the gulp task below, I encounter an error: Module not found: Error: Can't resolve 'app.ts' in 'wwwroot/js/admin' gulp.task("admin:js", function (done) { module.exports = { context: "wwwroot/js/admin", ...

Guide on bringing in Javascript file into your Ionic/Angular application

Within my Ionic 2 application, I have incorporated three.js along with a PLYLoader extension for three.js (accessible here: https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/PLYLoader.js) Integrating three.js is straightforward by includi ...

Leverage the power of Web Components in Vue applications

Currently, I am attempting to reuse Web Components within a Vue Component. These Web Components utilize the template element for formatting output. However, when I insert them into the Vue Template, they are either removed from the DOM or compiled by Vue. ...

Using Angular 2 global pipes without requiring PLATFORM_PIPES

I was interested in utilizing a feature to create a global pipe and came across this link: https://angular.io/docs/ts/latest/api/core/index/PLATFORM_PIPES-let.html However, I discovered that it is deprecated with the following message: Providing platform ...

Tips for choosing a specific quantity and adjusting its value

Just starting out with Ionic 3 and looking for some help with the code. Can anyone assist me in understanding how to change the value of an item in a shopping cart and have the subtotal reflect that change? cart.ts private _values1 = [" 1 ", "2", " 3 "," ...

Is there a similar function to $.ajax for React.js and Angular.js?

Can you guide me on how to send data using both React and Angular? Is there a similar function to $.ajax in React and Angular frameworks? I am looking for a post function that works like the one shown below in both React and Angular: $.ajax{ url:"test.p ...

Having trouble connecting JSON data to TreeTable Js through knockout.js?

I found a helpful plugin called TreeTable that I am using. You can check it out here: <table id="example-basic"> <thead> <tr> <th>Name</th> <th>Status</th> <th>id</th> ...

Passing data and events between components in React

I'm currently working on developing a dashboard app that includes a basic AppBar and a drawer. I based my design on this Demo. https://codesandbox.io/s/nj3u0q?file=/demo.tsx In the Demo, the AppBar, Drawer, and Main content are all contained within ...

What is the best way to incorporate a set of buttons and dynamically update them by using next and previous buttons?

Currently, I have code for two sets of buttons. How can we add functionality for next and previous buttons? <div id="chart-section-wrapper" class="container"> <div id="chart-section"> <div class=& ...