Angular loop over reactive form controls from HTML - javascript

I have a HTML table that is creating a TR component based on an ngFor loop.
<tbody>
<tr *ngFor="let t of intakeForm.controls['tasks'].value let i = index; trackBy:trackByIndex" [taskTR]="t" [ui]="uiOptions" [tasks]="configuredTasks" [intakeForm]="intakeForm"></tr>
</tbody>
Currently, I am looping over the value of the form for these controls but I am trying to loop over the controls instead so I can pass them to the trcomponent.
Something like:
let t of intakeForm.controls['tasks'].controls
tasks is a form array and I am trying to loop over the array of controls it has so that I can pass it to the component.
I tried this let t of (<FormArray>intakeForm.controls['tasks'].controls) but it didn't work. Not sure that it can be done within the html like that.
End goal here is that I want to pass the form control on each iteration to the tr component.

Try using the get method within form groups to inspect specific controls. It's a much cleaner way of accessing controls within form groups.
Also using the methodology below allows you to "drop" into each element within the array and access the properties directly within your template since you are already "within" the correct formGroup in the FormArray. So no need for long prefixes with indices to define which element of the FormArray you are working on.
<ng-container formArrayName="tasks">
<tr [formGroupName]="i" *ngFor="let task of intakeForm.get('tasks').controls; let i=index">
<input type="text" formControlName="taskName" />
</tr>
</ng-container>

Related

Hide a particular instance of a repeating component

I have a table with an ngFor iterating over a collection. For each item in the collection it will produce a row containing a single cell. The cell contains a button and custom component. The custom component has an ngIf directive which only shows the custom component if the device is deemed to be online. I'd like to be able to toggle the visibility of the custom component by clicking the button also. How do I pass the particular instance of the custom component in the table cell to the onExampleBtnClick() function? I do not wish to show/hide all instances of the custom component, only the one that shares the cell with the clicked button. Thanks
<table>
<tr *ngFor="let item of items;let indexOfelement=index;">
<td>
<button type="button" (click)="onExampleBtnClick($event)" #ExampleButton>Click Me</button>
<custom-comp *ngIf="showIfDeviceOnline"></custom-comp>
</td>
</tr>
</table>
You can create another property on your data array which will keep track of if the component need to be shown or not. You dont need to touch existing data creating a new array of object using map function like below.
export class AppComponent {
title = "CodeSandbox";
Items:string[] = ['Apple','Oranges'] ;
data: any = null;
ngOnInit(){
this.data = this.Items.map(x=> {
return {
name: x,
show:true
}
});
}
hide(item){
item.show = false;
}
}
and based on that you can apply *ngIf condition on container like below.
<div>
<div *ngFor="let item of data">
<ng-container *ngIf="item.show">
<button type="button" (click)="hide(item)"> Click Me</button>
<app-custom></app-custom>
</ng-container>
</div>
</div>
Here is the codesandbox
https://codesandbox.io/s/pedantic-forest-871qc?file=/src/app/app.component.ts:160-449
Another approach is the create a mapper object which will keep track of status of each item of array and based on the status hide the component.
Local references is what I was looking for. I can wrap the custom component in a div and apply a local reference of #CustComp and then pass CustComp to the onExampleBtnClick function. It will reference the actual instance and allow me to target it's hidden property.

Dynamically appending child nodes with Ionic CSS

I want to add styles from the Ionic CSS library to the HTML element created in Javascript. The purpose is because I'm pulling objects from my database and dynamically creating buttons for them. I can receive these items and add them to the page but I'm unable to use format it properly. This is a basic HTML example of what I want to replicate in JavaScript.
<ion-list id="list" (click)=add()>
<button ion-item>
<ion-icon name="ios-add" item-start></ion-icon>
Add
</button>
</ion-list>
To produce this button:
This is what I have in Javascript.
add() {
var listItem = document.getElementById("list");
var listButton = document.createElement('button');
listButton.setAttribute("class","ion-item");
listButton.setAttribute("id", id+"1");
var icon = document.createElement("ion-icon");
icon.setAttribute("name","ios-add");
let text = document.createTextNode("Add");
listButton.appendChild(text);
listButton.appendChild(icon);
listItem.appendChild(listButton);
}
This is what the above[code produces:
How can I use JavaScript to manipulate the DOM while retaining Ionic formatting?
Using: Node 8.3.0, Angular 4, Ionic 3.
I have a similar problem, what I am pushing the objects to an array every time I clicked on an object, I would push it to the array created in the front-end and display the array of objects in a separate component, that way I can style only the selected items.
The other option would be to copy the whole data objects and add props of boolean type like "added" or "in_playlist" but there may be a lot of data therefore I would suggest the first solution.

Get table attribute or property value within ember controller

I have an ember application which has a table and a grid component within a page. I have enabled drag and drop feature which drags a value from a particular cell of a table and drops it into the empty space of the grid. As the tables have more than one column, I want to get the index position or I want to know which column's cell is being dragged. I want that index value of column within the controller.
Suppose a table has 3 rows with 3 columns. For all the elements within the first column being dragged, I want to get the index value as 1 similarly for 2nd and 3rd column.
Here is my .hbs code for the table
<table class = "table table-bordered">
<thead>
<tr>
<th colspan="6">Inbound Units</th>
</tr>
</thead>
<tbody>
{{#each currentbid as |currentbid|}}
<tr>
{{#each pull as |pull|}}
{{#if (eq pull.DRIVERNAME currentbid.DRIVERNAME)}}
<td abbr="P1">{{#draggable-object content=pull position=1 dragEndAction='dragEndAction'}}{{#draggable-object-target action="draganddrop"}}{{pull.P1}}{{/draggable-object-target}}{{/draggable-object}}</td>
<td>{{pull.P2}}</td>
<td>{{pull.P3}}</td>
<td>{{pull.P4}}</td>
{{/if}}
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
As you can see wihtin the table td tag, I have specified abbr attribute. But I have no idea how to get the value of abbr within the controller. Any other way of getting this is also fine.
Thanks !
This answer applies to Ember 2.x.x and was written as of 2.15.
By default, actions assigned to a specific event via closure, like ondragEnd={{action "someAction"}} receive the event target as an argument:
actions: {
someAction(event) {
console.log(event.target)
}
}
Possibly, you could use event.target.parentElement.className in your component to get the class name, then send the action and argument to your controller. Hopefully that selector will return the new parent and not the old one.
You can read about different ways to catch browser events in the Ember Guides.

Vue.js weird rendering with class binding

So basically I have an html table with a v-for that loops over an array of objects, nothing complicated here. When the user clicks on a row, it toggles the selected property of the object "linked" to the given row.
Now, I also setup a simple class-binding with v-bind:class="{'active': n.selected}" where n is my object, but it doesnt update. Now what is more weird is that I use the webpack template from the vue-cli, and when I :
Select a bunch of rows (no active class binded)
update code
hit F5 which triggers the webpack hot-reload
The selected rows suddenly get the active class, as the CSS says so, until the webpack hot-reload has regenerated the page.
Here is my code :
<tr
v-for="n in node.children"
track-by="id"
v-on:click="toggleElement(n)"
v-bind:class="{'active': n.selected}">
<td>
<i class="icons">
<i class="folder yellow icon"></i>
</i>
</td>
<td><a v-on:click.stop="getLevel(n.id)">{{ n.name }}</a></td>
<td><span v-if="n.modification_date">{{ n.modification_date | moment "calendar"}}</span><span v-else>-</span></td>
<td><span v-if="n.size">{{ n.size }}</span><span v-else>-</span></td>
And for the javascript method
toggleElement: function(element) {
element.selected = !!(element.selected === undefined || !element.selected);
},
Now some more details, the objects are being retrieved by an ajax call, and the selected property doesnt exist from the start.
Any advice or solution ?
Thanks a lot!
by default,vue.js can not track the property you add after vue instance had been created
BUT,there is some method you can call to tell vue that new properties been added:
vm.$set('selected', true) //this will make "selected" propertie
trackable
First, do not forget to add the closing </tr> in your code.
Second, you can not add new attributes on objects after creating them with VueJS.
If when creating the element, its attribute selected was undefined, then VueJS will not add the getter/setter on it and changing it won't update the interface.
You will need to add the selected attribute before passing it to VueJS.

alternating class in ng-repeat using scope var without binding

I have a nested ng-repeat on a table. It is an accordion table with child rows for each parent row. In order to accomplish this I created a <tbody> for each parent item, placing the parent row in a <tr> and then using ng-repeat to add all the child rows. Due to the multiple <tbody> elements the zebra striping on the table gets thrown off. Another wrinkle is that the table has the ability to collapse/expand child rows and I need the striping to be correct for whichever rows are visible. So I am trying to manually add striping classes. I'm using Angular's ng-init to toggle a scope variable, and then using ng-class to apply it. The problem is that it appears to be bound to the final state of the variable rather than what it was as the iterator was rendering the row.
HTML:
<tbody ng-repeat="parentRow in myData" ng-init="changeRowClass($even)">
<tr ng-class="{'industry-payments-even-row':industryRowEven,'industry-payments-odd-row':!industryRowEven}">
<td>{{parentRow.industryCode}} - {{parentRow.industryCodeDescription}}</td>
<td class="numeric">{{parentRow.ValueOneSum}}</td>
<td class="numeric">{{parentRow.ValueTwoSum}}</td>
</tr>
<tr ng-repeat="childRow in parentRow.childIndustries" ng-init="changeRowClass($even)" ng-class="{'industry-payments-even-row':industryRowEven,'industry-payments-odd-row':!industryRowEven}">
<td>{{childRow.industryCode}} - {{childRow.industryCodeDescription}}</td>
<td class="numeric">{{childRow.ValueOne}}</td>
<td class="numeric">{{childRow.ValueTwo}}</td>
</tr>
</tbody>
Controller code:
$scope.industryRowEven = false;
$scope.changeRowClass = function(isEven) {
$scope.industryRowEven = isEven;
};
I need each iteration (of parent OR child) to reverse the class for the next one (I'm leaving out the issue of if the child is visible or not for now to keep this more simple). I can see in the debugger that the variable is getting toggled properly on each iteration. The problem is that the ng-class seems to be bound to the current state in scope so when it is true it would apply one class, but then next time it is false and switches the class for all of them.
I need it to just print the class according to the variable state at the time it renders that row, and then ignore the variable unless the ng-repeat is started over (like for sorting or toggling visibility, etc.)
Is there a way to stop the binding?
AngularJS has this build in with directives called ngClassOdd and ngClassEven.
They work just like ngClass, but only on odd/even items inside an ngRepeat.

Categories

Resources