how can i use ng2 component like react - javascript

I'm new to angular2.in my react project, my component looks like this:
export const DefaultButton = (props: Props) => {
return <button {...props}>{props.children}</button>
}
<DefaultButton>delete</DefaultButton>
ng2:
#Component({
selector: "button-default",
template`<button>{{text}}</button>`,
styleUrls: ["./default.css"]
})
export class ButtonDefaultComponent {
#Input() private text: string
}
can i use ng2 like this?
<button-default>delete</button-default>

The other two answers are close, but I think what you want is in the comment by #yurzui. You don't need an #Input decorated value, if all you're trying to do is pass down the word "delete" like in React. You can just use <ng-content>.
#Component({
selector: "button-default",
template: '
<button>
<ng-content></ng-content>
</button>
',
styleUrls: ["./default.css"]
})
export class ButtonDefaultComponent { }
and
<button-default> Delete </button-default>

If i understood you correctly, you want to have "delete" string inside your component as part of text input variable.
Your ts code is good, just change implementation of component in html:
<button-default [delete]="'delete'"></button-default>

Component
#Component({
selector: "button-default",
template`<button>{{text}}</button>`,
styleUrls: ["./default.css"]
})
export class ButtonDefaultComponent {
#Input("delete") private text: string
}
index
<button-default delete="delete"></button-default>
that is.

Related

Problem calling one Angular component from another component

At work, I have run into a problem using Angular. I have this kind of Angular component:
#Component({
selector: 'foo',
templateUrl: 'foo.html'
})
export class FooComponent {
#Input() data: string;
content: string;
ngOnInit() {
this.content = this.data;
}
setValue(data) {
this.content = data;
}
}
This is initialized from my main Angular component in a code block such as this:
this.components = [FooComponent, BarComponent, BazComponent, QuuxComponent];
Now this works so far. But if I try to call the setValue() function with this.components[0].setValue("Hello world!"); I get an error "this.components[0].setValue is not a function."
What is the reason for this and how can I fix it?
This seems like a very very weird way to work with components in angular.
You really don't want to break encapsulation by calling methods inside one component from another component.
I personally haven't seen this kind of component referencing anywhere (and have doubts it is a correct approach).
There is no reason to duplicate the data property in the content.
You can pass values in the template. Or use a service if you don't have direct access to the template.
Here is a very basic example on how to modify data from the parent using a template and #Input.
app.component.ts
import { Component } from "#angular/core";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
message = "I am a message from the parent";
}
app.component.html
<app-child [content]='message'></app-child>
child.component.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("content") public content: string;
constructor() {}
ngOnInit() {}
}
child.component.html
<p>{{content}}</p>

Communicating between child and parent components with ngAfterViewInit

So I try to communicate between components with ngAfterViewInit.
And I want to use the property
participant: ParticipantInfoDTO;
also using in other component. So I try it like this
#Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.scss'],
template: 'Example: {{participant}}<app-echeq-selector></app-echeq-selector>'
})
export class DetailComponent implements OnInit, AfterViewInit {
#ViewChild(EcheqSelectorComponent) echeqReference: ParticipantInfoDTO;
participant: ParticipantInfoDTO;
constructor(private dialog: MatDialog, route: ActivatedRoute) {
this.participant = route.snapshot.data['participant'];
}
ngOnInit() {
}
ngAfterViewInit(): void {
this.participant = this.echeqReference;
}
}
And in child component(EcheqSelectorComponent) I want it using like this:
<p> selected id:{{participant}} </p>
But I get an error on this line:
#Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.scss'],
template: 'Example: {{participant}}<app-echeq-selector></app-echeq-selector>'
})
saying:
Component 'DetailComponent' must not have both template and
templateUrlng(0)
Thank you
Remove template property in your component decorator.
In detail.component.html, add all the elements you want so that your html file looks like this:
Example: {{participant}}<app-echeq-selector></app-echeq-selector>
If you want to pass a property to app-echeq-selector component then you can use property binding like this:
<app-echeq-selector [participant]="participant"></app-echeq-selector>
In echeq component.ts:
export class echeq... {
#Input() participant;
// you can use this participant property as you want now.
}

How to set value to parent component property when a button is clicked in Child component in Angular

I am new to Angular 7 (2+) & trying my hands on #Input & #Output. However, passing data from Parent to Child component via #Input is understood & in place.
However, very basic on the other hand passing data from Child to Parent component via using #Output concept is understood & but the implementation is not getting right.
Here is what I am trying. When a button is clicked in the
Child component, a property in the parent component should be
converted to Upper case & displayed.
ChildComponent.ts
import { Component, OnInit, Input, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-child',
templateUrl: './child.component.html',
})
export class ChildComponent implements OnInit {
#Input('child-name') ChildName: string;
#Output() onHit: EventEmitter<string> = new EventEmitter<string>();
constructor() { }
ngOnInit() {}
handleClick(name): void {
this.onHit.emit(name);
}}
ChildComponent.html
<h1> child works! </h1>
<button (click)="handleClick('eventEmitter')"> Click me! </button>
ParentComponent.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
title = 'my-dream-app';
customerName: string = "";
catchChildEvent(e) {
console.log(e);
}}
ParentComponent.html
<div style="text-align:center">
<app-child [child-name]="HelloChild"></app-child>
//Trying to bind to Custom event of child component here
<b (onHit)="catchChildEvent($event)">
<i> {{customerName}} </i>
</b>
No error in console or binding
From the above snippet, when the button in Child Component is clicked the parent Component's property CustomerName should get the value & displayed?
Example: https://stackblitz.com/edit/angular-3vgorr
(onHit)="catchChildEvent($event)" should be passed to <app-child/>
<app-child [child-name]="HelloChild" (onHit)="catchChildEvent($event)"></app-child>
You are emitting event from app-child component so attach the handler for app-child component to make it work.
<div style="text-align:center">
<app-child (onHit)="catchChildEvent($event)" [child-name]="HelloChild"></app-child>
//Trying to bind to Custom event of child component here
<b>
<i> {{customerName}} </i>
</b>
And within the ts file update value of cutomerName property.
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
title = 'my-dream-app';
customerName: string = "";
catchChildEvent(e) {
this.customerName = e;
}
}
You should move (onHit)="catchChildEvent($event)" to app-child in parent html:
<app-child [child-name]="HelloChild"
(onHit)="catchChildEvent($event)>
</app-child>

Angular pass input variable to another component on button click

I come from a Python background, but I started trying to learn Angular and I'm really having trouble. Working between components is confusing to me and I can't figure it out. I made a good example that I think if someone helped me with it would go along way towards understanding Angular.
I just have two components: a "header" component and an app component. In the header component, I ask for the user's name and they click a button, and then it should show "Hello {{name}}" in the next component. I cannot get it to work to say the least and it's really frustrating. The Header part seems to work okay, but it's just not communicating with the other component at all. Neither the button part or the "name" part are working so I am clearly misunderstanding something I need to do when it comes to listening from the parent component.
Here is my Header HTML:
Name: <input type="text" id="userInput" value="Joe">
<button (click)=showName()>Show More</button>
Here is my Header TS:
import { Component, OnInit, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
bodyDiv = false;
inputName = '';
#Output() buttonClicked = new EventEmitter();
constructor() { }
ngOnInit() {
}
showName() {
console.log('showName clicked.');
this.bodyDiv = true;
this.inputName = document.getElementById('userInput').value;
console.log(this.inputName);
console.log(this.bodyDiv);
this.buttonClicked.emit(this.bodyDiv);
this.buttonClicked.emit(this.inputName);
}
}
Here is the main Component's HTML:
<app-header (buttonClicked)='showNextComponent($event)'></app-header>
<p *ngIf="![hiddenDiv]" [inputName]="name">Hello {{ name }} </p>
Here is the main component's TS:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
hiddenComponent = true;
title = 'show-button';
showNextComponent() {
console.log('Button clicked.');
this.hiddenComponent = false;
console.log(this.hiddenComponent);
}
}
So who can show me what I'm doing wrong and help figure out Angular a little better? :) Thank you!
replace showName function with below code :
showName() {
console.log('showName clicked.');
this.bodyDiv = true;
this.inputName = document.getElementById('userInput').value;
console.log(this.inputName);
console.log(this.bodyDiv);
this.buttonClicked.emit(this.inputName);
}
replace below code in your main component.
name:string
showNextComponent(value:string) {
this.name = value;
}
replace below code in your html :
<app-header (buttonClicked)='showNextComponent($event)'></app-header>
<p *ngIf="name">Hello {{ name }} </p>
Please let me if you have any question and I would suggest try to use ngmodel or something else instead of directly communicating with the DOM.
Here is a slightly modified and working sample: https://stackblitz.com/edit/angular-jhhctr
The event emitter in the header component emits the name (string) which is the $event in showNextComponent($event). You have to capture this in the main component and assign it to a local variable to be able to use it in the main component's template as {{name}}
[inputName]="name" is incorrect. You can pass values like that to angular components not to actual HTML DOM elements.
There are couple of ways to communicate from one component to another in angular - Using #Input()in your child component will expects an input from parent component and #Output() from your child component will emit an event from the child component
So in your case if you want to pass a value from parent to child you need to use input property or decorator on your child property - I will provide you the code but just go through proper guidance from the link provided this will make you to create better angular applications https://angular.io/guide/component-interaction
First you need to swap your components your header component should be your parent and the child component will be your main component - if you want to work in the same way just move your codes vice versa
Header html
Name: <input type="text" id="userInput" name='userInput' [(ngModel)]='inputName' value="Joe">
<button (click)=showName()>Show More</button>
<div [hidden]='bodyDiv'>
<app-header [bindName]='inputName'></app-header>
</div>
Header Component
import { Component, OnInit, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
bodyDiv = true;
inputName = '';
constructor() { }
ngOnInit() {
}
showName() {
bodyDiv = false;
}
}
Main Component Html
<p>Hello {{ bindName }} </p>
Main component ts
import { Component, Input } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
#Input()
bindName: string;
}
In your header component the inputName property will be binded using two way data binding where i used [(ngModel)]='inputName' so whatever you enter in the input text it will be updated in your inputName property
Now we need to do only one thing just to show your child component with any event - so when the button is clicked the div with [hidden] property will be false and it will be displayed and as we pass the inputName to the child Component it will be updated
And finally the child component will be displayed and the input written in the text will be updated in the child component - when the child component html displays the bindName will be updated and there will be result you expected
That's all I think this should work well - Try this and let me know - Thanks Happy coding !!
Don't forget to look into the link above where you can see many types of component interactions

String interpolation in Angular 2 not displaying updated value

I'm trying to learn Angular 2, and I'm running into a weird issue while following this documentation: https://angular.io/docs/ts/latest/guide/user-input.html for binding button clicks to a method on my controller.
I started off with their click event binding example. I created a simple app with the angular cli with ng new test-app and modified it so that it contains a single button that when I click, just adds a message to the page.
I have two components, the app component and the message components shown here:
message.component.html:
<p>{{message}}</p>
message.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-message',
templateUrl: './message.component.html',
styleUrls: ['./message.component.css']
})
export class MessageComponent implements OnInit {
message: string;
constructor() {
this.message = 'some initial message';
}
ngOnInit() {
}
}
app.component.html:
<button (click)="addMessage()">Click</button>
<app-message *ngFor="let message of messages"></app-message>
app.component.ts:
import { Component } from '#angular/core';
import { MessageComponent } from './message/message.component';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
messages = [];
addMessage() {
const newMessage = new MessageComponent();
newMessage.message = 'Something else entirely';
this.messages.push(newMessage);
}
}
When I run this with ng serve, the button appears as expected, but when I click the button, only the message some initial message appears despite being given a different value by my app controller. While doing a search I found a different way to do the one-way databinding by replacing the string interpolation with: <p [innerText]="message"></p> but the result is the same.
I'm kinda at a loss here as to why it won't display the updated value of Something else entirely.
MessageComponent component should take message as #Input:
export class MessageComponent implements OnInit {
#Input() message: string;
}
AppComponent should send this input to its child like
<app-message *ngFor="let message of messages"
[message]="message.message"></app-message>

Categories

Resources