How to pass a distinct identifier to an Angular 2 component?

Encountering an issue with Angular2 where I need to assign a unique identifier to my reusable component. Seeking assistance from the community.

account.html

<div class="container">
      <!-- ACCOUNT INFO -->
      <div class="row">
        <!-- ACCOUNT FORM -->
        <div class="col-sm-12">
          <div class="row">
            <div class="col-sm-4">
              <p>Name</p>
            </div>
            <div class="col-sm-6">
              <ar-account-editable-string [type]="'text'" [name]="'name'" [placeholder]="'Enter the name'"
                [text]="user?.username" (changed)="user.lastName = $event">
              </ar-account-editable-string>
            </div>
            <div class="col-sm-2 action-type">
              <div *ngIf="user.lastName">
                <a href (click)="enableAction()">Edit</a>
              </div>
              <div *ngIf="!user.lastName">
                <a href (click)="enableAction()">Add</a>
              </div>
            </div>
            <div class="col-sm-12">
              <ar-toggleable-account-section [inactive]="inactive" (activated)="$event">
              </ar-toggleable-account-section>
            </div>
          </div>
          <div class="row">
            <div class="col-sm-4">
              <p>Password</p>
            </div>
            <div class="col-sm-6">
              <div *ngIf="oldPassword">
                <ar-account-editable-string [type]="'password'" [name]="'oldPassword'" [placeholder]="'Current Password'" [text]="oldPassword" (changed)="oldPassword = $event">
                </ar-account-editable-string>
              </div>
              <div *ngIf="newPassword">
                <ar-account-editable-string [type]="'password'" [name]="'newPassword'" [placeholder]="'New Password'" (changed)="newPassword = $event">
                </ar-account-editable-string>
                <ar-account-editable-string [type]="'password'" [name]="'repeatNewPassword'" [placeholder]="'Repeat New Password'" (changed)="newPassword = $event">
                </ar-account-editable-string>
              </div>
            </div>
            <div class="col-sm-2 action-type">
              <div *ngIf="user.password">
                <a href (click)="enableAction()">Edit</a>
              </div>
              <div *ngIf="!user.password">
                <a href (click)="enableAction()">Add</a>
              </div>
            </div>
            <div class="col-sm-12">
              <ar-toggleable-account-section [inactive]="inactive" (activated)="$event">
              </ar-toggleable-account-section>
            </div>
          </div>

The 'ar-toggleable-account-section' in the above HTML is initially inactive, becoming active upon user interaction with the 'Edit' or 'Add' buttons.

Within account.component.ts:

protected inactive: boolean = true;
protected enableAction():boolean {
    this.inactive = false;
    return false;
  }

In toggleable-account.component.html:

<div class="col-sm-offset-4" *ngIf="!inactive">
  <a href (click)="save()">Save</a>
  <a href (click)="cancel()">Cancel</a>
</div>

toggleable-account.component.ts

import {
  Component, Input, Output, ViewChild, ViewEncapsulation, EventEmitter
} from '@angular/core';

@Component({
  selector: 'ar-toggleable-account-section',
  templateUrl: './toggleable-account.component.html',
  encapsulation: ViewEncapsulation.None
})
export class ToggleableAccountButtonComponent {

  /**
   * set the inactive state of the component
   * @type {boolean}
   */
  @Input() inactive:boolean = true;

  @Output() action = new EventEmitter<string>();

  protected save():void {
    this.action.emit('save');
  }

  protected cancel():void {
    this.action.emit('cancel');
  }

}

editable-account-string.component.html:

<input type="{{type}}"
        placeholder="{{placeholder}}"
        value="{{text}}" 
        [readonly]="text ? 'true': null" />

editable-account-string.component.ts:

import {
  Component, Input, Output, ViewEncapsulation, EventEmitter
} from '@angular/core';

@Component({
  selector: 'ar-account-editable-string',
  templateUrl: './editable-account-string.component.html',
  encapsulation: ViewEncapsulation.None,
})
export class EditableAccountStringComponent {
  @Input() type:string = 'text';
  @Input() placeholder:string = 'Enter some text...';
  @Input() name:string = '';
  @Input() text:string = '';

  @Output() changed = new EventEmitter<string>();


}

Issue:

Struggling with keeping track of multiple 'Save' and 'Cancel' buttons appearing on screen due to a shared [inactive] attribute across components like 'lastName', 'password', etc. Need help implementing unique/dynamic values for each instance such as user.lastName, user.password, user.email, etc.

If you have a solution, your input would be greatly appreciated!

Answer №1

One approach you could take is to pass the item being added/edited to the enable function and then check in the component's input if it matches the item being added/edited.

account.component.ts

protected addEditProp = '';
protected enableAction(prop: String) {
    this.addEditProp = prop;
}
protected finishedAddEdit(result: String) {
    this.addEditProp = '';
}

toggleable-account-component.ts (renamed variable)

@Output() accountResult = new EventEmitter<string>();

account.html (Note the use of accountResult in the

<ar-toggleable-account-section>
)

<div class="col-sm-2 action-type">
    <div *ngIf="user.lastName">
        <a href (click)="enableAction('lastName')">Edit</a>
    </div>
    <div *ngIf="!user.lastName">
        <a href (click)="enableAction('lastName')">Add</a>
    </div>
</div>
<div class="col-md-12>
    <ar-toggleable-account-section [inactive]="addEditProp === 'lastName'" (accountResult)="finishedAddEdit($event)">
    </ar-toggleable-account-section>
</div>
<div class="col-sm-2 action-type">
    <div *ngIf="user.password">
        <a href (click)="enableAction('password')">Edit</a>
    </div>
    <div *ngIf="!user.password">
        <a href (click)="enableAction('password')">Add</a>
    </div>
</div>
<div class="col-sm-12">
    <ar-toggleable-account-section [inactive]="addEditProp === 'password'" (accountResult)="finishedAddEdit($event)">
    </ar-toggleable-account-section>
</div>

Remember to reset the addEditProp when done adding/editing and emitting save or cancel to the parent component, similar to the finishedAddEdit(result: String) function.

addEditProp = '';



[UPDATE] (Display input for editing lastName/password etc.)

To show the input field for lastName or password based on which "Edit" button they clicked.

I've added an *ngIf to check if userAction is 'edit' and addEditProp is 'lastname'

<div class="col-sm-6" *ngIf="userAction === 'edit' && addEditProp === 'lastname'">
     <ar-account-editable-string [type]="'text'" [name]="'name'" [placeholder]="'Enter the name'" [text]="user?.username" (changed)="user.lastName = $event">
     </ar-account-editable-string>
</div>
<div class="col-sm-2 action-type">
    <div *ngIf="user.lastName">
        <a href (click)="enableAction('lastName', 'edit')">Edit</a>
    </div>
    <div *ngIf="!user.lastName">
        <a href (click)="enableAction('lastName', 'add')">Add</a>
    </div>
</div>

account.component.ts

protected addEditProp = '';
protected userAction = '';
protected enableAction(prop: String, userAction: String) {
    this.addEditProp = prop;
    this.userAction = userAction;
}
protected finishedAddEdit(result: String) {
    this.addEditProp = '';
    this.userAction = '';
}

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

ReactiveForm recursion encounters difficulty locating formGroups within the template

In order to dynamically create a large form with around 400 inputs, I am utilizing a meta-data object to pass input-specific information such as type of input, select options, step size, etc. However, I have encountered an issue where the parent form is no ...

Display the dynamic change of minutes and seconds every second on an Ionic HTML page

I created a JavaScript countdown counter that displays minutes and seconds using the following line of code: document.getElementById("demo").innerHTML = Number(this.minutes) + 'm' + Number(this.seconds) + 's '; However, on iOS devices ...

The function "AAA" is utilizing the React Hook "useState" in a context that does not fit the requirements for either a React function component or a custom React Hook function

Upon reviewing this code snippet, I encountered an error. const AB= () => { const [A, setA] = useState<AT| null>(null); const [B, setB] = useState<string>('0px'); ..more} ...

Merge two RxJS Observables/Subscriptions and loop through their data

Working with Angular (Version 7) and RxJS, I am making two API calls which return observables that I subscribe to. Now, the challenge is combining these subscriptions as the data from both observables are interdependent. This is necessary to implement cer ...

Encountering an Uncaught ReferenceError in Angular 8 and Webpack 4: Issue with vendor_lib not being defined plus source map error

Recently, I started working on a relatively simple interface that was initially developed in Angular2. As someone new to Angular2 and webpack, there were some challenges. I successfully upgraded the project from Angular 2.4 to Angular 8.0. Additionally, ...

Is it possible to dynamically adjust the container size based on its content with the help of *ngIf and additional directives?

I have a single-image container that I need to resize when editing the content. The size should adjust based on the incoming content. See the images of the containers below: Image 1: This is the container before clicking on the edit button. https://i.sst ...

Leverage the JSON Web Token module within a Chrome extension

Currently in the process of developing a chrome extension but encountering an issue with loading the json web token node module in my Node.js setup. background-script.ts import jwt from 'jsonwebtoken'; // import * as jwt from '../node_mod ...

Stop openapi-generator from altering enum names in JavaScript/TypeScript

We have implemented the openapi generator to create our REST client and it has been quite effective. However, we encountered an issue when using enums in the format UPERCASE_UNDERSCORE, as it ended up removing the underscores which caused inconvenience. Th ...

How can we create external labels for a polar chart in ng2-charts and chart.js, with a set position outside the circular rings?

Currently, I am working on creating a polar chart using Angular along with chart.js version 2.8.0 and ng2-charts version 2.3.0. In my implementation, I have utilized the chartjs-plugin-datalabels to show labels within the polar chart rings. However, this p ...

Disarrayed generic parameters in TypeScript

The title of the question may not be perfect, but it's the best I could do. Imagine a scenario where there is a function that accepts a callback along with an optional array. The callback takes an index and another optional array as parameters, and t ...

Delete the text in MUI's TablePagination component that displays the number of rows per page and the total rows in the table

Currently, I am integrating MUI's tablePagination component into my React table with TypeScript. I am looking to remove/disable the circlemarked text displayed in the image (the picture is an example from MUI). https://i.stack.imgur.com/ib0t2.png Af ...

Guide on utilizing CanActivateFn in Angular 16 through constructor-based injection techniques

How do I utilize the latest CanActivateFn feature in Angular 16 with Dependency Injection? The new version of Angular 16 now uses a function instead of a class for the canActivate functionality. Below is my implementation. How can I incorporate my depende ...

Elevate the Appearance of Material UI Elements with custom CSS Sty

I am currently facing an issue while trying to customize the styling of a Material UI component using CSS. Here is the code snippet: <IconButton className="my-class"> <Close /> </IconButton> CSS: .my-class { float: right ...

What is the best way to convert a JSON string received from Angular into a Java Object within a Spring

I am currently utilizing WebSocket to create a chat application. Below is the code from my Angular application that sends a MessageModel object to the backend after converting it into a JSON string: sendMessage(message: MessageModel){ let data = JSON.str ...

Enhance the functionality of a module by incorporating plugins when Typescript definitions are divided into multiple files

During my exploration of Typescript 2.2, I encountered a challenge in defining a module for HapiJS with various plugin options. To streamline the core code, I split it into multiple .d.ts files and then imported and re-exported them all from the index.d.t ...

Retrieving a data type from the key values of deeply nested objects

I'm currently working with JSON data that contains nested objects, and my goal is to extract the unique set of second-level keys as a type. For instance: const json = { 'alice': { 'dogs': 1, 'birds': 4 ...

Using Typescript and Next.js to handle error messages returned from Axios responses

My Next.js application makes an API call to validate a registration form. The server returns error messages in the following format: {"message":"The given data was invalid.","errors":{"email":["The email has alr ...

Ways to categorize by a particular date

const vehicleDetails = [ { "record_id": "2ff8212f-5ec9-4453-b1f3-91840a3fb152", "status_date_activity": { "On Rent": 1662021991000 } }, { "record_id": "c8c1 ...

Using [file_id] as a dynamic parameter in nextjs pages

I am working with a nextjs-ts code in the pages/[file_id].tsx file. import Head from 'next/head'; import Script from 'next/script'; import Image from 'next/image'; import Link from 'next/link'; import { NextApiReques ...

The ngOnInit lifecycle hook is not triggered by the Angular routerLink

In the component.ts file, you will find the ngOnInit function as shown below: ngOnInit() { this.locationService.getLocation().subscribe( locations => { this.locations = locations; }); } <a [routerLink]="['/locations-list&apo ...