Pairing or Connecting input and button elements with angular - html

I was following the tutorial Tour of Heroes. While adding a new hero they say
You can use an element paired with an add button.
Insert the following into the HeroesComponent template, after the heading:
<div>
<label for="new-hero">Hero name: </label>
<input id="new-hero" #heroName />
<!-- (click) passes input value to add() and then clears the input -->
<button type="button" class="add-button" (click)="add(heroName.value); heroName.value=''">
Add hero
</button>
</div>
Here I don't understand what is #heroName inside in input element (what is it called) and how does it help in pairing that input element with the button element.
Basically, what is that #<keyword> syntax within that input element. I know that it is not the id as that is already declared.

To answer the question, it's a reference to the input. You can find more details here:
https://angular.io/guide/template-reference-variables
Template variables help you use data from one part of a template in
another part of the template. Use template variables to perform tasks
such as respond to user input or finely tune your application's forms.
In the tutorial context, it's a reference to the input element. It helps to pair it with a button to be able to access it's value, without having to actually define a variable in the component.ts and trying to update the template directly. This help you "skip" a step, and actually have direct access to that value.
Template reference variables can become very handy in certain cases and are commonly used for example in angular material ( to call a function for a component )
<mat-menu #menuComponent ...></mat-menu>
<button (click)="menuComponent.close()"></button>
In the above example, you bind the menuComponent variable to "mat-menu" component, in which case you can access all the variables, public methods of such. In that case we can call "close" method from the mat-menu component.
Let me know if this is still unclear and I can try to give you more examples and explanation

Related

How to get a I18n variable value I can return to my Angular parent component?

I'm new to Angular and I just put in place an i18n (2 languages) system for a website I am creating. Everything works properly but in order to switch from one language to another in my header, I feel stuck.
I followed the Angular documentation to transfer my variables from child to parent component and I ended with this:
<input type="text" id="item-input" #lang>
<button type="button" (click)="changeChosenLang(lang.value)">
{{ 'global.lang' | translate }}
</button>
As you can see, I write my language in the input form and I send it to the proper component with a button. What I wanted was to click on my 'global.lang' text and to be able to send its value to the parent component, since the value is the language which is not actually used.
I don't know how to put my 'global.lang' text in a variable, neither what kind of balise I can use. Also I didn't know how to summarize my problem to search for it on StackOverflow so if you know a similar post, don't hesitate to post the link.
Thank you for your reading!
I found a less tortured way (poor brain) to have the result I wanted:
<span (click)="changeChosenLang()">
{{ 'global.lang' | translate }}
</span>
First I temporary changed my button to a span balise and I deleted the parameter from my changeChosenLang() function. Then, I transferred a variable 'lang' from my parent component to this one, witch contains the value of the language chosen in my app constructor. At each click, I change its value in my changeChosenLang() function and everything works great!
I hope it can help someone someday. The moral of this post is: the simpler, the better! Have a good day.

Minimal example to wrap a library component in angular12

In developing an Angular app, I find myself using similar HTML components with the same arugments over and over. For example:
<fa-icon class="tms-hover-animation px-2" (click)="onDeleteContact(row)"
[icon]="faTrash" ngbTooltip="Delete Contact" placement="bottom auto" container="body">
The placement and container fields are redundantly defined over and over and over. What I'd much rather be able to do is the following:
<my-fa-icon (click)="onDeleteContact(row)" [icon]="faTrash"></my-fa-icon>
However,I can't find an minimal example of how to do this.
To clarify: my main misunderstanding is how can I reuse <fa-icon and pass all of its inputs (click, icon, etc... ) without having to explicitly redeclare them in my wrapper? Something like:
#Component
FaIconWrapper
args: <-- These automatically passed into underlying fa-icon
How could we create a custom HTML element like this with default arguments, but still pass (click), [icon] and any other inputs down into the wrapped component?
I'm also worried about falling into an anti-pattern here.

React build own components

Sometimes I need some special UI component e.g multiple range slider, but I don't like using third party libraries, so usually I create component on my own. Over time I absolute stop using form tag, instead of that, I use just div and instead of onSubmit use just onClick, which call function, which return data from redux (also use my own redux form implementation). For example:
<div>
<div className="form-title">Some random Form</div>
<div className="form-body">
<Input
type="text"
label="Name: *"
form="random_form"
name="name"
/>
</div>
<div className="form-footer">
<Button onClick={()=> handleSubmit()}>Save</Button>
</div>
</div>
const handleSubmit = () => {
const form = getForm("random_form")
}
In this case I use component Input, which return normal html input (). But now I thinking that i will create some other pseudo form component, which will be build from some span and div. And my question - Is okay, when I don't use form tag and create own form component, which haven't default html equivalent.
Because of accessibility issues, it's generally preferable to have a form tag if you're making a form, but as other people mentioned, it's not required.
You do lose some functionality if you don't have a form tag. For example, if you had an input with required, it would get validated when the form is submitted, but since there is no form, it's not validated automatically. One of the more subtle issues I've encountered is that browsers might not save your input for autocompletion if no submit event happens.

The best way to make the view, a read-only of routeroutlet 's sections in angular ts

I am trying to make the mid-section to be read only and just enabling the button "OPEN".
I have the below original code. "router-outlet" renders the combination of several feature components. And I do not want to disable each and every elements or feature components
<div="row mid-section">
<router-outlet></router-outlet>
</div>
<div class="row">
<button class="btn btn-default"> OPEN </button>
</div>
I tried by adding as below:
<div="row mid-section" readonly="readonly">
But it still allows to edit and click on button inside mid-section div.
I would really appreciate your help. Thank you!
The HTML readonly property doesn't work like that. Its only for form fields and must be on that actual DOM element.
https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/readonly
Without seeing more of your code, I can't really give a better answer than these 2 options.
Option 1, a shared service that has that read only property. You could have a service, that has a behavior subject that you can update from the parent component. The inner components would all need to have that service injected, and do something appropriate when the value changes.
Option 2, you would need a container component that has a new boolean input, and it would need to pass that value down to all the children components (which would also need an input).

Angular2 function call from html element with no load event (or similiar)

I am new to Angular and have run into a problem that seems to have a javascript work around but they aren't very elegant.
I have a model with an array property. I ngfor the list property to build some html selection options. This is all working nicely. The problem comes when I am trying to set default value...the html elements don't have a load event.
I tried numerous html elements and they don't appear to have a load event either but I certainly could be doing it wrong.
I have seen a solution to put javascript tag right after the html and I could do that but I was really looking for a more elegant way in Angular.
I saw this SO post and thought that was my answer but there is a warning given that I agree with and thus it doesn't appear to be a good solution.
Regardless I tried it just to see if it would work and I got:
Failed to execute 'setAttribute' on 'Element': '{{loadDefaults()}}' is not a valid attribute name
<span {{loadDefaults()}} ></span>
So how can I fire an AS2 function in the component to load the default values?
HTML (btw this is NOT a full page load so there is no body tag):
<tr>
<td *ngFor="let loc of locOptions;">
<span>{{loc.text}}</span>
<input type="radio" name="radiogroup" [value]="loc.value" (change)="onSelectionChange(loc.value)">
</td>
</tr>
Edit
I thought perhaps mistakenly that ngoninit would fire too soon...before the html elements are rendered.
So perhaps what is being suggested is that I add a boolean is default to the model and bind THAT as the element is rendered.
In your ngonit function set this.locOptions to your default values. The value can be changed later on in any function and the change will be reflected in the view. Hope this helps you.
You should use ngOnInit to init you data, and call retrieve your data from your component :
defaults : any;
ngOnInit {
this.defaults = loadDefaults();
}
loadDefaults() {
//get data
}
HTML :
<span>{{defaults}}</span>