How to block duplicate values while inserting value into an array? - html

How to prevent duplicate values during insert record into an array using angular6+
PARENTCOMPONENT.HTML:
<div class="form-group" style="margin-left:30px;margin-top:30px;">
<input type="text" class="form-control" placeholder="Posts" name="post" [(ngModel)]="post" #clearText>
</div>
<button type="submit" class="btn btn-sm btn-primary" (click)="AddServer(post)"
style="margin-left:30px;margin-top:10px;" (blur) = "clearText.value = ''">Click</button>
<app-child [childPost]="parentPosts"></app-child>
PARENTCOMPONENT.TS:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
post = '';
parentPosts: any[] = [];
constructor() { }
ngOnInit() {
}
AddServer(post)
{
this.parentPosts.push(post);
console.log(post);
}
}
CHILDCOMPONENT.HTML:
<div style="margin-left: 30px; margin-top:10px;" *ngFor="let p of childPost">
<p>{{p}}</p>
</div>
CHILDCOMPONENT.TS:
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
#Input() childPost: any[] = [];
constructor() { }
ngOnInit() {
}
}
Hi guys the above code was insert data from parent component to child component using textbox values and button in that PARENCOMPONENT.TS code what i need is during the time of pushing value into an array the values must be unique if i post repeated value it throws an alert or error message the value was already inserted like that so please kindly help me to resolve this....

You could use Set data structure that will omit duplicate Insertions which is better then having an extra loop to verify if it's already in the array and then omit it.
parentPosts: Set = new Set();
// then use it like
this.parentPosts.add(post); // if post already exists it'll just not add it

Test if it contains it first
if (!this.parentPosts.includes(post)) {
this.parentPosts.push(post);
}

Related

Angular: How to send string values to another component using EventEmitter?

I have a parent component and a child component, I want to send 2 values from the child component via EventEmitter to the parent component as I want to use the printMessages() function there.
I have a click event on the child component which emits 2 string values, but I'm unsure how to connect the emit event to the parent component and for the printMessages() function to run. How can the parent component read these values into the "printMessages()" function and for that function to run after the values have reached it? As you can see, I currently have no HTML in the parent component, perhaps I need to do something there?
Parent Component:
import { Component } from '#angular/core';
#Component({
selector: 'parent-component',
template: ``,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
// Function in which I want to send values from the child component.
printMessages(string1: string, string2: string) {
console.log(string1, string2);
}
Child Component:
import { Component, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'child-component',
template: `
<button (click)="sendStrings()">Send Strings</button>
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
#Output() message = new EventEmitter();
constructor() { }
sendStrings(){
this.message.emit({string1:"Hello", string2:"World!"});
}
}
You need to react on the child components event within the template and call the method.
import { Component } from '#angular/core';
#Component({
selector: 'parent-component',
template: `<child-component (onMessage)="printMessages(e)"></child-component>`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
printMessages(event) {
// strings are included in event object
}
}

Cannot access the parent formControl object changes in a Parent-Child Component relationship in Angular 8

I have created a parent component as follows:
<form [formGroup] = "cardForm">
<app-inputvalidator [controls] = "cardForm.get('name')"></app-inputvalidator>
</form>
Parent ts file
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl,Validators } from '#angular/forms';
#Component({
selector: 'app-card-form',
templateUrl: './card-form.component.html',
styleUrls: ['./card-form.component.css']
})
export class CardFormComponent implements OnInit {
nameFormControl ;
cardForm = new FormGroup({
name: new FormControl('', [Validators.minLength(5),Validators.maxLength(25)])
});
constructor() {
}
ngOnInit(): void {
this.nameFormControl = this.cardForm.get('name');
}
}
I am passing the nameFormControls to the child component and accessing it in the template as well as class as follows:
InputValidator.ts
import { Component, OnInit, Input } from '#angular/core';
import { FormControl} from '#angular/forms';
#Component({
selector: 'app-inputvalidator',
templateUrl: './inputvalidator.component.html',
styleUrls: ['./inputvalidator.component.css']
})
export class InputvalidatorComponent implements OnInit {
#Input() controls: FormControl;
constructor() {
}
ngOnInit(): void {
}
}
Input Validator.html
<input [formControlName] = "controls"
<br>
<div>{{ controls.errors | json}}</div>
The project is compiled successfully with no errors.
I am getting the value of controls.errors to always null.
Why can I not print the object controls.errors using string interpolation as the value in the name input box changes?
you get null becuase you don't put required validator the min,maxLength validators will return an error if there is value and the value is not valid , if the value is null or empty string this will consider a valid
check the validator 👉 source

How to get check particular checkboxes by default based on some values in angular 7

I have a checkboxes and selectbox whose values are coming from loop,but here I need to get some checkboxes checked by default based on an array of object.Here checkbox and selectbox value is coming from usersg and usersr variable.But the checked and selected by default should be from variable usersg_checked and usersr_selected inside ngOnInit(). Here is the code below
home.component.html
<p *ngFor="let group of usersg"><input type="checkbox" checked="checked.id" value="{{group.id}}" />{{group.name}}</p>
<p><select><option *ngFor="let role of usersr" value="{{role.id}}">{{role.name}}</option></select></p>
home.component.html
import { Component, OnInit } from '#angular/core';
import { CommonserviceService } from './../utilities/services/commonservice.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
submitted = false;
usersg_checked:any;
usersr_selected:any;
constructor(private formBuilder: FormBuilder) {
}
public usersg = [{"id":1,"name":"test1"},{"id":2,"name":"test2"},{"id":3,"name":"test3"},{"id":4,"name":"test4"}];
public usersr = [{"id":1,"name":"test1"},{"id":2,"name":"test2"}];
ngOnInit() {
this.usersg_checked = [{"id":1,"name":"test1"},{"id":2,"name":"test2"}];
this.usersr_selected = [{"id":1,"name":"test1"}];
}
}
Add isChecked() method in component to check if a checkbox must be selected.
Component:
isChecked(id) {
return this.usersg_checked.some(item => item.id === id);
}
Template:
<p *ngFor="let group of usersg">
<input type="checkbox" [checked]="isChecked(group.id)" value="{{group.id}}" />{{group.name}}
</p>
For <select> elements better to use [(ngModel)].
Template:
<p><select [(ngModel)]="usersr_selected.id">
<option *ngFor="let role of usersr" value="{{role.id}}">{{role.name}}</option>
</select></p>
Component:
And change usersr_selected to an object.
ngOnInit() {
this.usersr_selected = {"id":1,"name":"test1"};
}
If usersr_selected is an array, use the first element of the array as NgModel.
ngOnInit() {
this.usersr_selected = this.usersr_selected[0];
}

Kind of recursive usage of an Component possible?

After searching for like two hours for a solution I decided to ask some pros suspecting the solution could be quite simple.
It is an Angular7 project.
I would like to have a "goal" in my goals component with a button "+". When you click that button I want to have annother goal being added to the page. So I want to click a button of the goal component to create a new goal, which is something like recursive to me.
goals.component.html:
<input type="text" value="Ich brauche einen Laptop für maximal 1000 Euro.">
<br/>
<br/>
<app-goal id="{{lastGivenId+1}}"></app-goal>
goals.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-goals',
templateUrl: './goals.component.html',
styleUrls: ['./goals.component.scss']
})
export class GoalsComponent implements OnInit {
lastGivenId: number = 0;
constructor() { }
ngOnInit() {
}
}
goal.component.ts and goal.component.html:
//Typescript code
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-goal',
templateUrl: './goal.component.html',
styleUrls: ['./goal.component.scss']
})
export class GoalComponent implements OnInit {
#Input() id : number;
constructor() { }
ngOnInit() {
}
onAddLowerGoal(currentGoalID:number){
// var goalElement = document.registerElement('app-goal');
// document.body.appendChild(new goalElement());
let newGoal = document.createElement("app-goal");
newGoal.setAttribute("id", "999");
let currentGoal = document.getElementById(currentGoalID.toString());
document.body.insertBefore(newGoal, currentGoal);
}
}
<html>
<div id="{{id}}" class="goal">goal{{id}}</div>
<button id="AddLowerGoal1" (click)="onAddLowerGoal(999)">+</button>
</html>
This way, it creates an app-goal element, but the div and button elements within the app-goal element is missing.
How can this problem be solved? Any help is welcome. Thanks in advance.
First glance: delete the html tags from your goal.component.html file.
Next: you can recursively add app-goal using angular. Inserting app-goal element the javascript way only adds the <app-goal></app-goal> object. It doesn't create an angular component. It doesn't bind your data.
Also if you're using Angular's #Input, you need to assign a component input with square braces. Do not use tags.
goals.component.html:
<input type="text" value="Ich brauche einen Laptop für maximal 1000 Euro.">
<br/>
<br/>
<app-goal [id]="lastGivenId+1"></app-goal>
goal.component.html:
<div id="{{id}}" class="goal">goal{{id}}</div>
<button id="AddLowerGoal1" (click)="onAddLowerGoal(999)">+</button>
<div *ngFor="let subGoal of subGoals">
<app-goal [id]="subGoal.id"></app-goal>
</div>
goal.component.ts:
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-goal',
templateUrl: './goal.component.html',
styleUrls: ['./goal.component.scss']
})
export class GoalComponent implements OnInit {
#Input() id : number;
subGoals: Array<any> = [];
constructor() { }
ngOnInit() { }
onAddLowerGoal(currentGoalID: number){
this.subGoals.push({id: currentGoalID});
}
}
You can also use a service to store your goals and subgoals to access them later.
I think what you're looking for is a Reactive Form with FormArray with dynamically added form controls.
Take a look at this for eg:
import { Component } from '#angular/core';
import { FormControl, FormGroup, FormArray, FormBuilder } from '#angular/forms';
#Component({...})
export class GoalsComponent {
goalsForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.goalsForm = this.fb.group({
goals: this.fb.array([])
});
}
onFormSubmit() {
console.log('Form Value: ', this.goalsForm.value);
}
get goals() {
return (<FormArray>this.goalsForm.get('goals')).controls;
}
addGoal() {
(<FormArray>this.goalsForm.get('goals')).push(this.fb.control(null));
}
}
And here's the template for this:
<h2>Goals:</h2>
<form [formGroup]="goalsForm" (submit)="onFormSubmit()">
<button type="button" (click)="addGoal()">Add Goal</button>
<hr>
<div *ngFor="let goal of goals; let i = index;" formArrayName="goals">
<div>
<label for="goal">Goal {{ i + 1 }}: </label>
<input type="text" id="goal" [formControlName]="i">
</div>
<br>
</div>
<hr>
<button>Submit Form</button>
</form>
Here's a Sample StackBlitz for your ref.

Angular html nesting

Let's say I have in some upper level class some angular template code that looks like this
<outer-component>
<a></a>
</outer-component>
Where <a> can be any module that extends a certain interface defined elsewhere, is there a way for <outer-component> be able to take <a> or whatever is placed inside the tags and communicate with it specifically be able to listen to functions or bind to variables in a way that is as succinct as the snippet above?
If you want to share data between a parent and a child (hierarchical relationship) you can use EventEmitter to allow the parent to get data from the child.
In the child component:
import { Component, Input, Output, EventEmitter } from 'angular/core';
#Component({
selector: 'app-child',
template: `
<h3>Child</h3>
Say {{message}}
<button (click)="sendMessage()"></button>
´,
styleUrls: ['pathToStyles.css']
})
export class ChildComponent {
message: string = "Hello world";
#Output() messageEvent = new EventEmitter<string>();
constructor() {}
sendMessage() {
this.messageEvent.emit(this.message);
}
}
In the parent component:
import { Component } from '#angular/core';
#Component({
selector: 'app-parent',
template: `
Message: {{message}}
<app-child (messageEvent)="receiveMessage($event)"></app-child>
`,
styleUrls: ['pathToStyles.css']
})
export class ParentComponent {
constructor() { }
message:string;
receiveMessage($event) {
this.message = $event
}
}