Angular - Two Way Binding - html

I am a beginner at Angular and I covering two way binding but for some reason I do not understand what I am doing wrong with the below any input would be appreciated.
I am simply trying to understand the concept so the below code is rather simple. Per my understanding
Adding the two way binding [()] to <app-child-comp> I pass the parent field "name" from the parent component to the parent view and using property binding it provides an initialization value ( default value ) to the child component that receives the value in the #Input field.
Once the field "#Input childName " has its value using normal interpolation I can use the value how ever I please in the child template.
Now by defining an EventEmitter and then using its .emit method I should be able to pass any changes on the variable back up to the parent component and update the DOM property to reflect the changes.
Problem:
Now this is my problem the parent --> child direction the bindings are working as intended,
the name "Fin" is appearing as I expect in the input of the parent Template and in the interpolation in the child template but when I want to alter the name in the child template and have it bubble back up to the parent property it fails to update although it updates the interpolation in the child template.
Ive been trying to figure this out now for a while and everything im researching I feel says im doing it correctly but if you could please explain what im doing wrong I would much appreciate it.

Im adding this so that anyone looking in the future can learn from my mistake.
There are two ways to perform event binding given a child component
The first way is by explicitly declaring the property and event bindings as follows <app-child-comp [childName]="name" (childNameChange)="name =$event"></app-child-comp>
The second way is to use the "Banana Box" Method where the child tag transforms into <app-child-comp [(childName)]="name"></app-child-comp>
I was trying to use the second method and something that wasn't immediately clear is that there is a naming convention when it comes to the field names in the child component that needs to be followed in order for the "Banana Method" to work
Rule: If your #Input field is named "x" then your #Output EventEmitter needs to be named "xChange" the "Change" is required as the second part of the name .
Syntax: inputName + Change
So in order to resolve my problem I needed to change the naming convention from
#Input() childName:string;
#Output() changedName = new EventEmitter<string>();
to
#Input() childName:string;
#Output() childNameChange = new EventEmitter<string>();

You have to add the output in your root component:
<app-child-app [(childName)]="name" (changedName)="name = $event"></app-child-app>

Related

concatenate variables in angular property element

I comment, and looked here and I can not find the solution, my problem is the following:
in my html template in angular, I need to pass a series of data to the metadata property of a button, I can't get the correct way to successfully concatenate the variable that contains the value.
this should be the html element:
<mati-button clientId="clientId" flowId="flowId" color="green"metadata='{"user_id":"1234778","email":"som#som.com"}'/>
I tried several ways but I can't insert the respective values....
example:
<mati-button metadata='{"userID": "{{user.id}}" }'></mati-button>
unsuccessfully...
Assuming mati-button is an Angular component with metadata as Input(), you are probably looking for
<mati-button
[clientId]="clientId"
[flowId]="flowId"
[color]="green"
[metadata]="{ userId: '1234778', email: 'som#som.com'}"
></mati-button>
See the guide on property binding to learn more:
To bind to an element's property, enclose it in square brackets, [], which identifies the property as a target property. [...] The brackets, [], cause Angular to evaluate the right-hand side of the assignment as a dynamic expression. Without the brackets, Angular treats the right-hand side as a string literal and sets the property to that static value.
By "dynamic expression" they mean JS-expressions, i.e., a public variable available through the component's TypeScript, a boolean expression, an array, or, like in your case, a JS-object that you can construct inline.
You can try doing this
<mati-button metadata="{'userID': user.id }"></mati-button>
metadata='{" userID ": {{user.id}}}'
in the end I got it. Apparently I don't know why, but the third-party script hides that parameter and it couldn't be debugged in the console, but it does receive them without any problem! Thanks everyone for your help!

Should you rather define several or only one input parameter (with all values) for child components

I am faced with the question of how I should set up my Angular components with regard to inputs.
The first variant would be to create an input variable for each given value. This means that you would have to enter each variable individually when calling it:
The second variant would be to pack all the required values ​​in a model and only include this model. So in the end only one input:
Now I don't know which of the two variants is better suited for a large app with many components.
Is there one i should prefer from these two or are there more i dont know yet?
It depends upon your component info what info you are passing for example if the component is a shared button in which expected inputs could be button name, class, status etc.
In that scenario instead of passing all inputs separately you could go with one object lets say props which contains button properties.
export interface IButtonProps {
text: string;
class: string;
disabled?: boolean;
}
buttonData: IButtonProps;
this.buttonData = {
...this.buttonData,
text: 'Submit',
class: 'primary',
disabled: false
}
In template instead of passing individual input pass an object of buttonData
<my-button [props]="buttonData"></my-button>
Your example doesn't really explain itself too well but here goes:
If your input's are all of the same type and used for the same thing, theres nothing wrong with putting all of them in an array and passing them to the child.
Instead of:
[input]="'string1'" [input2]="'string2'" you could do [input]="['string1', 'string2']"
However consider this:
[iconClass]="'my-icon-class'" [buttonClass]="'my-button-class'"
Each of the inputs do something completely different, so putting them inside of an array would be very bad practice.
What you could also do is put all inputs in an object, for example:
input = { iconClass: 'my-icon-class', buttonClass: 'my-button-class' };
[input]="input"
You should only be using this, if the inputs are somehow related or/and do the same thing / modify the same element in the child.

Angular 10 | Different ID types | How to add css style with css file

I do not really understand the difference between these three ways to declare an ID in html:
[id] = "'example'"
id = "example"
#example
The first two seem to be identical, is this correct?
These I can style in my example.component.css file.
The third one is special. I understand I can use it everywhere in the current html view, but I cannot apply CSS styles with example.component.css, is this correct?
Which one shall I use in angular? A combination of 1/2 and 3?
I also noticed if I use the same ID in different components, I will have duplicate ID's, which is really bad, so eventhough I use angular and different components I must be very careful how I name ID's, is this correct?
Version 2 is the default html syntax for an id
Version 1 is the angular way, if the id is a variable, e.g. [id]="myId"
Version 3 is the angular way to export/reference a html element to angular. This is not an id.
The id is a HTML Element (not angular), so you have to look that the id in html after building is unique.
Yes the first two have an identical end result. The second one is a string while the first one is a javascript expression and is evaluated by angular. This means you can use things like component properties such as [id]="'example-' . foo" which outputs id="example-2" if you had a property foo = 2; in your component.
The third one actually doesn't have anything to do with the ID attribute in HTML, but I understand why it may seem like it. It's actually a template reference variable and it allows you to access this element from anywhere else in your template, or even from your component code.
You're right, the html specification requires an ID to be unique, browsers are forgiving so they may permit you to use duplicate IDs but it should be avoided at all costs.
You can use id="unique_id" if you don't want to change it dynamically. If you want to change your HTML element id dynamically through Component.ts then you should use [id]="your_variable" & #example serves for different purpose described below.
id with [] brackets is angular directive to set HTML id attribute value through a variable or expression
id is a HTML attribute which sets a unique id on an element
#example if you are writing like this in Component.html you are basically creating a template reference variable which is a reference to a DOM element within a template. You can then access this using Angular #ViewChild decorator. It can also refer to a directive (which contains a component), an element, TemplateRef, or a web component.
Angular Template Reference Variable
[id] = "'example'" => This one set assign example as id and it is same as id = "example".
Suppose if we want to assign a variable value then use [id] = "example".For this in ts file you have to declare the example variable
Public example ="your-class-name";
So id value will be your-class-name
#example => These are templare refference variable.
A template reference variable is often a reference to a DOM element within a template.
For example,
<input #phone placeholder="phone number" />
<!-- lots of other elements -->
<!-- phone refers to the input element; pass its `value` to an event handler -->
<button (click)="callPhone(phone.value)">Call</button>

Angular - Setting value in input text box in another component

I am trying to set the value in an HTML input text box which is a part of ComponentA from the typescript code which is a part of ComponentB.
Taking a clue from this SO i tried doing:
(<HTMLInputElement>document.getElementById("name")).value = response.name;
But this is not working. Is there anything else i need to take care of?
EDIT: The element with Id "name" is in ComponentA and the above code that is trying to manipulate that element is in ComponentB
If you are trying to set the value of component1's textfield from the compoenent2 then you must have to use of ngModel i.e two way data binding. by providing component2 in the providers list you are able to access all the functions and variables of that component, then you can easily set your value. like this
suppose this is your component 2's value property
name:string = 'Pardeep Jain';
than you can access this in component like this-
<input type="text" [(ngModel)]='name'>
....
constructor(private delete1: Delete){
this.name = this.delete1.name;
}
Working Example
Also
(<HTMLInputElement>document.getElementById("name")).value = response.name;
is used to set the value of current template's field with id named as **name**
This is one of the cases when user interaction on one component ComponentA triggers an update on another component ComponentB.
This article describes multiple approaches, with example code, on how to pass information between components.
My personal favorite is the third approach mentioned in that article in which one of the component (say ComponentA) "listen" for update it is concerned about from any component (say ComponentB) via a service in between them, resulting in a loosely coupled components.
For more approaches here is another link.

As3 - Assign class to object on stage

I think the title should make it pretty clear. I was wondering how you can assign a class to an object on stage. As you would do with actionscript:
var objectname:ClassName = new ClassName();
This would make a new object, but the current object already exists, it just needs to be notified that it's of the type "ClassName" so it can inherit it's properties.
I've also tried assigning the "ClassName" in the linkage as either the base path or the class name. But in either situations I get an error saying that the class needs to be unique when I use the same class on multiple objects.
So I would need something like
//example exists on stage
example.class = ClassName
Thanks
I will answer your question with a question : why are you assigning the same class on multiple objects?
If what you want is a common behavior for those objects, you should create your class and assign it has the Base Class on those objects.
I don't think there's a way to do just do that. But I do suggest you look into the decorator design pattern The idea here is that you don't change the class, but you "decorate it" with more functions as needed.
Hope this helps !
You seem to have this the wrong way around. You define a class in order to set specific behavior & properties for an object. In a real life example, if I want to build a radio , I will come up with a radio design & implement it. Now if I need several radios, I will use the same implementation to manufacture them.
If I now wish to turn my radio into a TV , I can't just tell my radio, hey , you're a TV now. I can either decide beforehand that I want a radio/tv object and switch behavior whenever necessary or I can create a new TV object and add the radio functionality to it by adding a radio component to my TV object.
var radio:Radio // your current object
//example 1
radio.switchToTv();
//example 2
var radioTv:Tv = new Tv( radio );