How to create unique `id` attributes in AngularJS ng-repeat repeaters - html

I'm seeing this in our templates. They say it's so the code can be tested but it still seems wrong to me:
<tr ng-repeat="comp in collection">
<td>
<span id="someId">{{comp.someText}}</span>
</td>
....
I'm thinking we should be using name instead.

If you really need unique IDs inside the repeater, try this:
<tr ng-repeat="comp in collection">
<td>
<span id="someId{{$index}}">{{comp.someText}}</span>
</td>
So if, for instance, you need to link labels to inputs in the ngRepeat:
<tr ng-repeat="comp in collection">
<td>
<label for="field{{$index}}">{{field.label}}</label>
<input type="text" id="field{{$index}}" ng-model="field.value" />
</td>
This approach is especially useful if you need to have check boxes with clickable labels inside the ngRepeat.

Related

AngularJS ng-model filling out all my inputs in a ng-repeat

I'm trying to get the input value of my input HTML in an ng-repeat. but when I write in the HTML side the first input, it will fill out all the other inputs. How can I avoid this and dissociate all the inputs? see below my HTML part:
<tr ng-repeat="item in data.list track by item.sys_id">
<td ng-repeat="field in ::data.fields">{{::item[field].display_value}}</td>
<td>
<input type="text" class="form-control" placeholder="Comment" ng-model="c.data.comment">
</td>
</tr>
Thank you for your help :)
Define input as array and use different index for different inputs as ng-model, like this -
c.data.comment = ["input_0","input_1","" ...]
And use above based on index -
<td>
<input type="text" class="form-control" placeholder="Comment" ng-model="c.data.comment[$index]">
</td>
PS: please verify the syntax, this is how more or less you can handle this.

Get value from input-tag that is conditionally visible with *ngIf

I've got a simple form in HTML. Depending on the option chosen with the radio button, there are different input fields visible, using *ngIf.
<table>
<tr>
<td><label>name</label></td>
<td><input #name /></td>
</tr>
<tr>
<td>
<input type="radio" name="contact" value="phone" (click)="usePhone(true)" #p>
<label for"p">phone</label>
</td>
<td>
<input type="radio" name="contact" value="email" (click)="usePhone(false)" #m>
<label for"m">email</label>
</td>
</tr>
<tr *ngIf="phone">
<td><label>phone</label></td>
<td><input #phone /></td>
</tr>
<tr *ngIf="!phone">
<td><label>email</label></td>
<td><input #email /></td>
</tr>
<table>
In the TypeScript file, I declare a varibale "phone" of the type boolean and a method:
usePhone(phone: boolean): void {
this.phone = phone
}
Now, I want to get the values when clicking on a button:
<button (click)="add(name.value, phone.value, email.value);">
OK
</button>
But when I try it, the browser console says that phone is undefined, even when it is chosen and visible. When I delete the *ngIf statements, so that everything is visible, it works properly. What can I do?
Phone variable is undefined because when you set phone to false, #phone element is not rendered.
Hide rows instead of remove:
<tr [hidden]="!phone">
and
<tr [hidden]="phone">
*ngIf vs [hidden]
From angularjs official documentation:
Hiding an element is quite different from removing an element with
NgIf.
When you hide an element, that element and all of its descendents
remain in the DOM. All components for those elements stay in memory
and Angular may continue to check for changes. You could be holding
onto considerable computing resources and degrading performance, for
something the user can't see.
When NgIf is false, Angular removes the element and its descendents
from the DOM. It destroys their components, potentially freeing up
substantial resources, resulting in a more responsive user experience.
The show/hide technique is fine for a few elements with few children.
You should be wary when hiding large component trees; NgIf may be the
safer choice.
https://angular.io/guide/template-syntax#ngif
The issue lies in usePhone function. You are setting this.phone to boolean and are using it in html
as refrence to your input tag. You just need to change refrence variable name of the input tag like:
<td><input #phoneRef /></td>
And on click pass phoneRef.value:
<button (click)="add(name.value, phoneRef.value, email.value);">
We cant access variable inside *ngIf , you can use [hidden]
<tr [hidden]="!phone">
<td><label>phone</label></td>
<td><input #phone2 /></td>
</tr>
<tr [hidden]="phone">
<td><label>email</label></td>
<td><input #email /></td>
</tr>

Table with multiple rows doesn't work with forms in HTML

Basically, I have a table with inputs inside a form tag, that are required by user to fill in.
When I test it, the form is working, but only when there is one row in a table. With two an more rows, a required attribute is not working.
I've written a simple example
This works, click enter inside input field to see.
<form>
<table>
<tr>
<td>
<input type="text" name="usrname" required>
</td>
</tr>
</table>
</form>
<br>
This doesn't work, click enter inside input field to see.
<form>
<table>
<tr>
<td>
<input type="text" name="usrname" required>
</td>
</tr>
<tr>
<td>
<input type="text" name="surname" required>
</td>
</tr>
</table>
</form>
That's because forms with more than one text input aren't submitted by hitting enter. Try adding a submit button to both forms and you'll see it works fine.
In your example, is that supposed to be two identical fields in the different cells (and one of them is just misspelled)? If so, that's likely your problem. If they are intended to be two separate fields, it should work, but I'd need to see a more real-world example.
Also, I'd highly recommend using CSS to format/style your form. If that sounds intimidating, try Bootstrap--it makes creating pretty forms extremely easy.

html table elements not aligning with the row above

I'm having trouble with styling a table.
http://jsfiddle.net/Gs7Vx/5/
<tr>
<td class="label">HRS</td>
<td class="label">INSP</td>
</tr>
I want the "HRS" and "INSP" fields in this row to line up with the input fields above them. I've tried a lot of things, none of them have worked. I'm sure there's a simple solution and I'm just missing it.
To get the inputs to line up with the labels, you need to
A) add a blank <td></td> to the second row (because the row above it has 3 cells and it only has 2), and
B) remove float:right; from the .label class.
See this as the example. I only added the <td></td> to the row on the first out of your four sections, but they are all identical, so you get the point.
You would want to setup your table like this:
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td>HRS</td>
<td>
<input type="text" class="smallinput">
</td>
</tr>
<tr>
<td>INSP</td>
<td>
<input type="text" class="smallinput">
</td>
</tr>
<tr>
<td colspan="2">
<textarea name="textarea" rows="12" class="txt"></textarea>
</td>
</tr>
</table>
Next time format your code before posting. You did not make your intent clear. SO we have multiple people giving you different answers because we are formatting your code and trying to figure out what you really want to do. Make sure you have the same number of <td>s in each row as well or use colspan to make up for the missing ones.
Check this fiddle.
the row above that row containing only two <td>s with content 'hrs' and 'insp', contains 3 <td>s. Hence you need to put a blank td in that row(i.e. with 'hrs' and 'insp') too.
Besides you need to remove the style float:right and add the style position:relative in the style definition of the .smallinput-class.
O/P
This solves your problem..
I took it out of these <td class="label"></td> and put it right in front and it worked fine.
INSP<input type="text" class="smallinput"></td><td width="40px" style="font-size:12px">HRS<input type="text" class="smallinput">
(using chrome.)
your code is all wrong. First of all, you have unclosed elements, all input elements should end with />
Then, to have everything in a line, do it like this:
<tr>
<td>label</td>
<td>input</td>
<td>label</td>
<td>input</td>
</tr>
an then style as needed
this worked for me
<tr>
<td class="fieldtitle"><i style="color:#fff;" class="icon"></i>
</td>
<td width="40px" style="font-size:12px">
<input type="text" class="smallinput"><span style="font-size:10px">HRS</span>
</td>
<td width="40px" style="font-size:12px">
<input type="text" class="smallinput"><span style="font-size:10px">INSP</span>
</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>

How put form into two td elements?

Let's assume I have the following structure
<table>
<tr>
<td>
<input type="text" name="name" />
</td>
<td>
<input type="submit" name="submit" />
</td>
</tr>
...
</table>
I need to have forms in each row, but because my inputs are in other <td> elements, I don't know how to place the <form> element (of course I can use colspan="2" and put the form into it, but I need to have two other <td> elements).
How can I solve this?
UPDATE: I don't want to use Javascript to solve this problem :)
Just place the tags around the table:
<form action="...">
<table>
...
</table>
</form>
This form will "handle" all the input fields inside the table.
The best solution: Use divs instead of tables.
Other solution, create a separate table for each row. That way, you can put each table in a separate form and put the input fields in the td-s, so they will be inside the form too.
You can make a table, and in the table cells, create a form, and in the form, create another table:
<table>
<tr><td>
<form>
<table>
<tr><td>
....
</tr></td>
</table>
</form>
</tr></td>
</table>
I am pretty sure it is not possible to mix and match inputs in a form if the forms don't follow each other sequentially i.e. "assign" an input to a form.